Merge "Support larger guard regions."
diff --git a/README.md b/README.md
index cd409d9..7114015 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
+Using bionic
+============
+
+See the [additional documentation](docs/).
+
Working on bionic
=================
@@ -43,7 +48,7 @@
#### benchmarks/ --- benchmarks
-The `benchmarks/` directory contains benchmarks.
+The `benchmarks/` directory contains benchmarks, with its own [documentation](benchmarks/README.md).
What's in libc/?
@@ -298,35 +303,6 @@
The coverage report is now available at `covreport/index.html`.
-Running the benchmarks
-----------------------
-
-### Device benchmarks
-
- $ mma
- $ adb remount
- $ adb sync
- $ adb shell /data/nativetest/bionic-benchmarks/bionic-benchmarks
- $ adb shell /data/nativetest64/bionic-benchmarks/bionic-benchmarks
-
-When operated without specifying an xml file, the default is to use the xml
-file called full.xml found in the directory `suites/` bound in the same directory
-as the bionic-benchmarks executable.
-
-To use a different xml file, use the `--bionic_xml=FILE.XML` option. By default, this
-option searches for the xml file in the `suites/` directory. If it doesn't exist
-in that directory then the file will be found as relative to the current
-directory. If the option specifies the full path to an xml file such as
-`/data/nativetest/suites/example.xml`, it will be used as is.
-
-You can use `--benchmark_filter=getpid` to just run benchmarks with "getpid"
-in their name.
-
-### Host benchmarks
-
-See the "Host tests" section of "Running the tests" above. The default for
-host tests is to use the `host.xml` file in the suites directory instead of `full.xml`.
-
Attaching GDB to the tests
--------------------------
@@ -341,54 +317,4 @@
32-bit ABI bugs
---------------
-### `off_t` is 32-bit.
-
-On 32-bit Android, `off_t` is a signed 32-bit integer. This limits functions
-that use `off_t` to working on files no larger than 2GiB.
-
-Android does not require the `_LARGEFILE_SOURCE` macro to be used to make
-`fseeko` and `ftello` available. Instead they're always available from API
-level 24 where they were introduced, and never available before then.
-
-Android also does not require the `_LARGEFILE64_SOURCE` macro to be used
-to make `off64_t` and corresponding functions such as `ftruncate64` available.
-Instead, whatever subset of those functions was available at your target API
-level will be visible.
-
-There are a couple of exceptions to note. Firstly, `off64_t` and the single
-function `lseek64` were available right from the beginning in API 3. Secondly,
-Android has always silently inserted `O_LARGEFILE` into any open call, so if
-all you need are functions like `read` that don't take/return `off_t`, large
-files have always worked.
-
-Android support for `_FILE_OFFSET_BITS=64` (which turns `off_t` into `off64_t`
-and replaces each `off_t` function with its `off64_t` counterpart, such as
-`lseek` in the source becoming `lseek64` at runtime) was added late. Even when
-it became available for the platform, it wasn't available from the NDK until
-r15. Before NDK r15, `_FILE_OFFSET_BITS=64` silently did nothing: all code
-compiled with that was actually using a 32-bit `off_t`. With a new enough NDK,
-the situation becomes complicated. If you're targeting an API before 21, almost
-all functions that take an `off_t` become unavailable. You've asked for their
-64-bit equivalents, and none of them (except `lseek`/`lseek64`) exist. As you
-increase your target API level, you'll have more and more of the functions
-available. API 12 adds some of the `<unistd.h>` functions, API 21 adds `mmap`,
-and by API 24 you have everything including `<stdio.h>`. See the
-[linker map](libc/libc.map.txt) for full details.
-
-In the 64-bit ABI, `off_t` is always 64-bit.
-
-### `sigset_t` is too small for real-time signals.
-
-On 32-bit Android, `sigset_t` is too small for ARM and x86 (but correct for
-MIPS). This means that there is no support for real-time signals in 32-bit
-code.
-
-In the 64-bit ABI, `sigset_t` is the correct size for every architecture.
-
-### `time_t` is 32-bit.
-
-On 32-bit Android, `time_t` is 32-bit. The header `<time64.h>` and type
-`time64_t` exist as a workaround, but the kernel interfaces exposed on 32-bit
-Android all use the 32-bit `time_t`.
-
-In the 64-bit ABI, `time_t` is 64-bit.
+See [32-bit ABI bugs](docs/32-bit-abi.md).
diff --git a/benchmarks/README.md b/benchmarks/README.md
index 6501839..9cb130d 100644
--- a/benchmarks/README.md
+++ b/benchmarks/README.md
@@ -1,10 +1,41 @@
Bionic Benchmarks
=================
+
Bionic benchmarks is a command line tool for measuring the runtimes of libc functions. It is built
on top of [Google benchmarks](https://github.com/google/benchmark) with some additions to organize
tests into suites.
-Instructions for running these can be found in the platform_bionic README.
+Running the benchmarks
+----------------------
+
+### Device benchmarks
+
+ $ mma
+ $ adb remount
+ $ adb sync
+ $ adb shell /data/nativetest/bionic-benchmarks/bionic-benchmarks
+ $ adb shell /data/nativetest64/bionic-benchmarks/bionic-benchmarks
+
+When operated without specifying an xml file, the default is to use the
+xml file called full.xml found in the directory `suites/` bound in the
+same directory as the bionic-benchmarks executable.
+
+To use a different xml file, use the `--bionic_xml=FILE.XML` option. By
+default, this option searches for the xml file in the `suites/`
+directory. If it doesn't exist in that directory then the file will be
+found as relative to the current directory. If the option specifies the
+full path to an xml file such as `/data/nativetest/suites/example.xml`,
+it will be used as is.
+
+You can use `--benchmark_filter=getpid` to just run benchmarks with "getpid"
+in their name.
+
+### Host benchmarks
+
+See the benchmarks/run-on-host.sh script. The default for host tests is
+to use the `host.xml` file in the suites directory instead of `full.xml`.
+The host benchmarks can be run with 32- or 64-bit bionic, or the host glibc.
+
## Suites
diff --git a/docs/32-bit-abi.md b/docs/32-bit-abi.md
new file mode 100644
index 0000000..eecbe6d
--- /dev/null
+++ b/docs/32-bit-abi.md
@@ -0,0 +1,59 @@
+32-bit ABI bugs
+===============
+
+`off_t` is 32-bit
+-----------------
+
+On 32-bit Android, `off_t` is a signed 32-bit integer. This limits functions
+that use `off_t` to working on files no larger than 2GiB.
+
+Android does not require the `_LARGEFILE_SOURCE` macro to be used to make
+`fseeko` and `ftello` available. Instead they're always available from API
+level 24 where they were introduced, and never available before then.
+
+Android also does not require the `_LARGEFILE64_SOURCE` macro to be used
+to make `off64_t` and corresponding functions such as `ftruncate64` available.
+Instead, whatever subset of those functions was available at your target API
+level will be visible.
+
+There are a couple of exceptions to note. Firstly, `off64_t` and the single
+function `lseek64` were available right from the beginning in API 3. Secondly,
+Android has always silently inserted `O_LARGEFILE` into any open call, so if
+all you need are functions like `read` that don't take/return `off_t`, large
+files have always worked.
+
+Android support for `_FILE_OFFSET_BITS=64` (which turns `off_t` into `off64_t`
+and replaces each `off_t` function with its `off64_t` counterpart, such as
+`lseek` in the source becoming `lseek64` at runtime) was added late. Even when
+it became available for the platform, it wasn't available from the NDK until
+r15. Before NDK r15, `_FILE_OFFSET_BITS=64` silently did nothing: all code
+compiled with that was actually using a 32-bit `off_t`. With a new enough NDK,
+the situation becomes complicated. If you're targeting an API before 21, almost
+all functions that take an `off_t` become unavailable. You've asked for their
+64-bit equivalents, and none of them (except `lseek`/`lseek64`) exist. As you
+increase your target API level, you'll have more and more of the functions
+available. API 12 adds some of the `<unistd.h>` functions, API 21 adds `mmap`,
+and by API 24 you have everything including `<stdio.h>`. See the
+[linker map](libc/libc.map.txt) for full details.
+
+In the 64-bit ABI, `off_t` is always 64-bit.
+
+
+`sigset_t` is too small for real-time signals
+---------------------------------------------
+
+On 32-bit Android, `sigset_t` is too small for ARM and x86 (but correct for
+MIPS). This means that there is no support for real-time signals in 32-bit
+code.
+
+In the 64-bit ABI, `sigset_t` is the correct size for every architecture.
+
+
+`time_t` is 32-bit
+------------------
+
+On 32-bit Android, `time_t` is 32-bit. The header `<time64.h>` and type
+`time64_t` exist as a workaround, but the kernel interfaces exposed on 32-bit
+Android all use the 32-bit `time_t`.
+
+In the 64-bit ABI, `time_t` is 64-bit.
diff --git a/docs/status.md b/docs/status.md
new file mode 100644
index 0000000..25f5663
--- /dev/null
+++ b/docs/status.md
@@ -0,0 +1,142 @@
+Android bionic status
+=====================
+
+libc
+----
+
+Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/libc/libc.map.txt
+
+New libc functions in P:
+ * `__freading`/`__fwriting` (completing <stdio_ext.h>)
+ * `getlogin_r`
+ * `iconv`/`iconv_close`/`iconv_open` (adding <iconv.h>)
+ * `syncfs`
+
+New libc functions in O:
+ * `sendto` FORTIFY support
+ * `__system_property_read_callback`/`__system_property_wait`
+ * legacy `bsd_signal`
+ * `catclose`/`catgets`/`catopen` (adding <nl_types.h>)
+ * `ctermid`
+ * all 6 <grp.h>/<pwd.h> (get|set|end)(gr|pw)ent functions
+ * `futimes`/`futimesat`/`lutimes`
+ * `getdomainname`/`setdomainname`
+ * `getsubopt`
+ * `hasmntopt`
+ * `mallopt`
+ * `mblen`
+ * 4 <sys/msg.h> `msg*` functions
+ * <langinfo.h> `nl_langinfo`/`nl_langinfo_l`
+ * `pthread_getname_np`
+ * 2 new Linux system calls `quotactl` and `sync_file_range`
+ * 4 <sys/sem.h> `sem*` functions
+ * 4 <sys/shm.h> `shm*` functions
+ * 5 legacy <signal.h> functions: `sighold`/`sigignore`/`sigpause`/`sigrelse`/`sigset`
+ * `strtod_l`/`strtof_l`/`strtol_l`/`strtoul_l`
+ * <wctype.h> `towctrans`/`towctrans_l`/`wctrans`/`wctrans_l`
+
+New libc functions in N:
+ * more FORTIFY support functions (`fread`/`fwrite`/`getcwd`/`pwrite`/`write`)
+ * all remaining `_FILE_OFFSET_BITS=64` functions, completing `_FILE_OFFSET_BITS=64` support in bionic (8)
+ * all 7 `pthread_barrier*` functions
+ * all 5 `pthread_spin*` functions
+ * `lockf`/`preadv`/`pwritev`/`scandirat` and `off64_t` variants
+ * `adjtimex`/`clock_adjtime`
+ * `getifaddrs`/`freeifaddrs`/`if_freenameindex`/`if_nameindex`
+ * `getgrgid_r`/`getgrnam_r`
+ * GNU extensions `fileno_unlocked`/`strchrnul`
+ * 32-bit `prlimit`
+
+libc function count over time:
+ G 803, H 825, I 826, J 846, J-MR1 873, J-MR2 881, K 896, L 1116, M 1181, N 1226, O 1278
+
+```
+ndk-r17$ for i in `ls -1v platforms/android-*/arch-arm/usr/lib/libc.so` ; do echo $i; nm $i | grep -vw [AbdNnt] | grep -vw B | wc -l ; done
+```
+
+Run `./libc/tools/check-symbols-glibc.py` in bionic/ for the current
+list of POSIX functions implemented by glibc but not by bionic. Currently
+(2017-09):
+```
+aio_cancel
+aio_error
+aio_fsync
+aio_read
+aio_return
+aio_suspend
+aio_write
+endhostent
+endnetent
+endprotoent
+endutxent
+fexecve
+fmtmsg
+getdate
+getdate_err
+getnetent
+getprotoent
+glob
+globfree
+hcreate
+hdestroy
+hsearch
+lio_listio
+posix_spawn
+posix_spawn_file_actions_addclose
+posix_spawn_file_actions_adddup2
+posix_spawn_file_actions_addopen
+posix_spawn_file_actions_destroy
+posix_spawn_file_actions_init
+posix_spawnattr_destroy
+posix_spawnattr_getflags
+posix_spawnattr_getpgroup
+posix_spawnattr_getschedparam
+posix_spawnattr_getschedpolicy
+posix_spawnattr_getsigdefault
+posix_spawnattr_getsigmask
+posix_spawnattr_init
+posix_spawnattr_setflags
+posix_spawnattr_setpgroup
+posix_spawnattr_setschedparam
+posix_spawnattr_setschedpolicy
+posix_spawnattr_setsigdefault
+posix_spawnattr_setsigmask
+posix_spawnp
+pthread_attr_getinheritsched
+pthread_attr_setinheritsched
+pthread_cancel
+pthread_getconcurrency
+pthread_mutex_consistent
+pthread_mutex_getprioceiling
+pthread_mutex_setprioceiling
+pthread_mutexattr_getprioceiling
+pthread_mutexattr_getprotocol
+pthread_mutexattr_getrobust
+pthread_mutexattr_setprioceiling
+pthread_mutexattr_setprotocol
+pthread_mutexattr_setrobust
+pthread_setcancelstate
+pthread_setcanceltype
+pthread_setconcurrency
+pthread_setschedprio
+pthread_testcancel
+sethostent
+setnetent
+setprotoent
+sockatmark
+swab
+wordexp
+wordfree
+```
+
+libm
+----
+
+Current libm symbols: https://android.googlesource.com/platform/bionic/+/master/libm/libm.map.txt
+
+0 remaining missing POSIX libm functions.
+
+19 new libm functions in O: complex trig/exp/log functions.
+
+libm function count over time:
+ G 158, J-MR2 164, L 220, M 265, O 284
diff --git a/libc/Android.bp b/libc/Android.bp
index 204ad19..8932be6 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -72,7 +72,6 @@
never: true,
},
native_coverage: false,
- clang: true,
}
// ANDROIDMK TRANSLATION ERROR: unsupported directive
@@ -218,6 +217,10 @@
"upstream-freebsd/lib/libc/gen/sleep.c",
"upstream-freebsd/lib/libc/gen/usleep.c",
"upstream-freebsd/lib/libc/stdlib/getopt_long.c",
+ "upstream-freebsd/lib/libc/stdlib/hcreate.c",
+ "upstream-freebsd/lib/libc/stdlib/hcreate_r.c",
+ "upstream-freebsd/lib/libc/stdlib/hdestroy_r.c",
+ "upstream-freebsd/lib/libc/stdlib/hsearch_r.c",
"upstream-freebsd/lib/libc/stdlib/qsort.c",
"upstream-freebsd/lib/libc/stdlib/quick_exit.c",
"upstream-freebsd/lib/libc/string/wcpcpy.c",
@@ -282,6 +285,7 @@
cflags: [
"-Wno-sign-compare",
"-Wno-uninitialized",
+ "-Wno-unused-parameter",
"-include freebsd-compat.h",
],
@@ -1567,7 +1571,11 @@
srcs: ["bionic/mmap.cpp"],
},
},
-
+ product_variables: {
+ treble: {
+ cflags: ["-D__ANDROID_TREBLE__"],
+ },
+ },
cppflags: ["-Wold-style-cast"],
local_include_dirs: ["stdio"],
include_dirs: ["bionic/libstdc++/include"],
@@ -1975,7 +1983,6 @@
local_include_dirs: ["arch-x86_64/include"],
},
},
- clang: true,
}
cc_defaults {
diff --git a/libc/NOTICE b/libc/NOTICE
index 90de7ef..feea29d 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -5644,6 +5644,31 @@
-------------------------------------------------------------------
+Copyright (c) 2015 Nuxi, https://nuxi.nl/
+
+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) 2017 Imagination Technologies.
All rights reserved.
diff --git a/libc/arch-x86/bionic/__set_tls.cpp b/libc/arch-x86/bionic/__set_tls.cpp
index 241d94a..3f58bc5 100644
--- a/libc/arch-x86/bionic/__set_tls.cpp
+++ b/libc/arch-x86/bionic/__set_tls.cpp
@@ -28,7 +28,6 @@
#include <limits.h>
#include <pthread.h>
-#include <stdbool.h>
#include <asm/ldt.h>
diff --git a/libc/bionic/__bionic_get_shell_path.cpp b/libc/bionic/__bionic_get_shell_path.cpp
index 477fa4a..41162e9 100644
--- a/libc/bionic/__bionic_get_shell_path.cpp
+++ b/libc/bionic/__bionic_get_shell_path.cpp
@@ -31,18 +31,24 @@
#include <sys/cdefs.h>
#include <unistd.h>
-__LIBC_HIDDEN__ static const char* __libc_system_sh = "/system/bin/sh";
-__LIBC_HIDDEN__ static const char* __libc_vendor_sh = "/vendor/bin/sh";
+#define VENDOR_PREFIX "/vendor/"
static const char* init_sh_path() {
- /* look for /system or /vendor prefix */
- char exe_path[7];
- ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
- if (len != -1 && !strncmp(exe_path, __libc_vendor_sh, sizeof(exe_path))) {
- return __libc_vendor_sh;
- }
+ /* If the device is not treble enabled, return the path to the system shell.
+ * Vendor code, on non-treble enabled devices could use system() / popen()
+ * with relative paths for executables on /system. Since /system will not be
+ * in $PATH for the vendor shell, simply return the system shell.
+ */
- return __libc_system_sh;
+#ifdef __ANDROID_TREBLE__
+ /* look for /system or /vendor prefix */
+ char exe_path[strlen(VENDOR_PREFIX)];
+ ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
+ if (len != -1 && !strncmp(exe_path, VENDOR_PREFIX, strlen(VENDOR_PREFIX))) {
+ return "/vendor/bin/sh";
+ }
+#endif
+ return "/system/bin/sh";
}
__LIBC_HIDDEN__ extern "C" const char* __bionic_get_shell_path() {
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index 39d6e09..fc9e74a 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -164,7 +164,7 @@
// Hunt for the region that contains that address.
FILE* fp = fopen("/proc/self/maps", "re");
if (fp == nullptr) {
- async_safe_fatal("couldn't open /proc/self/maps");
+ async_safe_fatal("couldn't open /proc/self/maps: %s", strerror(errno));
}
char line[BUFSIZ];
while (fgets(line, sizeof(line), fp) != NULL) {
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index dc1b984..09ae16c 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -59,14 +59,14 @@
size_t allocation_size = BIONIC_TLS_SIZE + (2 * PTHREAD_GUARD_SIZE);
void* allocation = mmap(nullptr, allocation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (allocation == MAP_FAILED) {
- async_safe_fatal("failed to allocate TLS");
+ async_safe_fatal("failed to allocate TLS: %s", strerror(errno));
}
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, allocation, allocation_size, "bionic TLS guard");
thread->bionic_tls = reinterpret_cast<bionic_tls*>(static_cast<char*>(allocation) +
PTHREAD_GUARD_SIZE);
if (mprotect(thread->bionic_tls, BIONIC_TLS_SIZE, PROT_READ | PROT_WRITE) != 0) {
- async_safe_fatal("failed to mprotect TLS");
+ async_safe_fatal("failed to mprotect TLS: %s", strerror(errno));
}
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->bionic_tls, BIONIC_TLS_SIZE, "bionic TLS");
}
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index abd403b..829194c 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -104,9 +104,13 @@
// Check if we're looking for ourselves before acquiring the lock.
if (thread == __get_thread()) return thread;
- ScopedReadLock locker(&g_thread_list_lock);
- for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) {
- if (t == thread) return thread;
+ {
+ // Make sure to release the lock before the abort below. Otherwise,
+ // some apps might deadlock in their own crash handlers (see b/6565627).
+ ScopedReadLock locker(&g_thread_list_lock);
+ for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) {
+ if (t == thread) return thread;
+ }
}
// Historically we'd return null, but
diff --git a/libc/bionic/strtold.cpp b/libc/bionic/strtold.cpp
index c55dd61..6b673e6 100644
--- a/libc/bionic/strtold.cpp
+++ b/libc/bionic/strtold.cpp
@@ -26,6 +26,8 @@
* SUCH DAMAGE.
*/
+#define __BIONIC_LP32_USE_LONG_DOUBLE
+
#include <float.h>
#include <stdlib.h>
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 6906ecd..c57cd9c 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -31,7 +31,6 @@
#include <fcntl.h>
#include <poll.h>
#include <stdatomic.h>
-#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/libc/bionic/tdestroy.cpp b/libc/bionic/tdestroy.cpp
index 95c3e64..2968ff9 100644
--- a/libc/bionic/tdestroy.cpp
+++ b/libc/bionic/tdestroy.cpp
@@ -14,10 +14,15 @@
* limitations under the License.
*/
-#define _SEARCH_PRIVATE
#include <search.h>
#include <stdlib.h>
+struct node_t {
+ char* key;
+ struct node* llink;
+ struct node* rlink;
+};
+
// Destroy a tree and free all allocated resources.
// This is a GNU extension, not available from BSD.
void tdestroy(void* root, void (*destroy_func)(void*)) {
diff --git a/libc/bionic/wcstod.cpp b/libc/bionic/wcstod.cpp
index f7bd433..41df854 100644
--- a/libc/bionic/wcstod.cpp
+++ b/libc/bionic/wcstod.cpp
@@ -26,6 +26,8 @@
* SUCH DAMAGE.
*/
+#define __BIONIC_LP32_USE_LONG_DOUBLE
+
#include <wchar.h>
#include <stdlib.h>
diff --git a/libc/include/complex.h b/libc/include/complex.h
index 79fe07c..3fe8f35 100644
--- a/libc/include/complex.h
+++ b/libc/include/complex.h
@@ -61,99 +61,99 @@
/* 7.3.5.1 The cacos functions */
double complex cacos(double complex __z) __INTRODUCED_IN(23);
float complex cacosf(float complex __z) __INTRODUCED_IN(23);
-long double complex cacosl(long double complex __z) __INTRODUCED_IN(26);
+long double complex cacosl(long double complex __z) __RENAME_LDBL(cacos, 23, 26);
/* 7.3.5.2 The casin functions */
double complex casin(double complex __z) __INTRODUCED_IN(23);
float complex casinf(float complex __z) __INTRODUCED_IN(23);
-long double complex casinl(long double complex __z) __INTRODUCED_IN(26);
+long double complex casinl(long double complex __z) __RENAME_LDBL(casin, 23, 26);
/* 7.3.5.1 The catan functions */
double complex catan(double complex __z) __INTRODUCED_IN(23);
float complex catanf(float complex __z) __INTRODUCED_IN(23);
-long double complex catanl(long double complex __z) __INTRODUCED_IN(26);
+long double complex catanl(long double complex __z) __RENAME_LDBL(catan, 23, 26);
/* 7.3.5.1 The ccos functions */
double complex ccos(double complex __z) __INTRODUCED_IN(23);
float complex ccosf(float complex __z) __INTRODUCED_IN(23);
-long double complex ccosl(long double complex __z) __INTRODUCED_IN(26);
+long double complex ccosl(long double complex __z) __RENAME_LDBL(ccos, 23, 26);
/* 7.3.5.1 The csin functions */
double complex csin(double complex __z) __INTRODUCED_IN(23);
float complex csinf(float complex __z) __INTRODUCED_IN(23);
-long double complex csinl(long double complex __z) __INTRODUCED_IN(26);
+long double complex csinl(long double complex __z) __RENAME_LDBL(csin, 23, 26);
/* 7.3.5.1 The ctan functions */
double complex ctan(double complex __z) __INTRODUCED_IN(23);
float complex ctanf(float complex __z) __INTRODUCED_IN(23);
-long double complex ctanl(long double complex __z) __INTRODUCED_IN(26);
+long double complex ctanl(long double complex __z) __RENAME_LDBL(ctan, 23, 26);
/* 7.3.6 Hyperbolic functions */
/* 7.3.6.1 The cacosh functions */
double complex cacosh(double complex __z) __INTRODUCED_IN(23);
float complex cacoshf(float complex __z) __INTRODUCED_IN(23);
-long double complex cacoshl(long double complex __z) __INTRODUCED_IN(26);
+long double complex cacoshl(long double complex __z) __RENAME_LDBL(cacosh, 23, 26);
/* 7.3.6.2 The casinh functions */
double complex casinh(double complex __z) __INTRODUCED_IN(23);
float complex casinhf(float complex __z) __INTRODUCED_IN(23);
-long double complex casinhl(long double complex __z) __INTRODUCED_IN(26);
+long double complex casinhl(long double complex __z) __RENAME_LDBL(casinh, 23, 26);
/* 7.3.6.3 The catanh functions */
double complex catanh(double complex __z) __INTRODUCED_IN(23);
float complex catanhf(float complex __z) __INTRODUCED_IN(23);
-long double complex catanhl(long double complex __z) __INTRODUCED_IN(26);
+long double complex catanhl(long double complex __z) __RENAME_LDBL(catanh, 23, 26);
/* 7.3.6.4 The ccosh functions */
double complex ccosh(double complex __z) __INTRODUCED_IN(23);
float complex ccoshf(float complex __z) __INTRODUCED_IN(23);
-long double complex ccoshl(long double complex __z) __INTRODUCED_IN(26);
+long double complex ccoshl(long double complex __z) __RENAME_LDBL(ccosh, 23, 26);
/* 7.3.6.5 The csinh functions */
double complex csinh(double complex __z) __INTRODUCED_IN(23);
float complex csinhf(float complex __z) __INTRODUCED_IN(23);
-long double complex csinhl(long double complex __z) __INTRODUCED_IN(26);
+long double complex csinhl(long double complex __z) __RENAME_LDBL(csinh, 23, 26);
/* 7.3.6.6 The ctanh functions */
double complex ctanh(double complex __z) __INTRODUCED_IN(23);
float complex ctanhf(float complex __z) __INTRODUCED_IN(23);
-long double complex ctanhl(long double complex __z) __INTRODUCED_IN(26);
+long double complex ctanhl(long double complex __z) __RENAME_LDBL(ctanh, 23, 26);
/* 7.3.7 Exponential and logarithmic functions */
/* 7.3.7.1 The cexp functions */
double complex cexp(double complex __z) __INTRODUCED_IN(23);
float complex cexpf(float complex __z) __INTRODUCED_IN(23);
-long double complex cexpl(long double complex __z) __INTRODUCED_IN(26);
+long double complex cexpl(long double complex __z) __RENAME_LDBL(cexp, 23, 26);
/* 7.3.7.2 The clog functions */
double complex clog(double complex __z) __INTRODUCED_IN(26);
float complex clogf(float complex __z) __INTRODUCED_IN(26);
-long double complex clogl(long double complex __z) __INTRODUCED_IN(26);
+long double complex clogl(long double complex __z) __RENAME_LDBL(clog, 26, 26);
/* 7.3.8 Power and absolute-value functions */
/* 7.3.8.1 The cabs functions */
double cabs(double complex __z) __INTRODUCED_IN(23);
float cabsf(float complex __z) __INTRODUCED_IN(23);
-long double cabsl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23);
+long double cabsl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(cabs)*/;
/* 7.3.8.2 The cpow functions */
double complex cpow(double complex __x, double complex __z) __INTRODUCED_IN(26);
float complex cpowf(float complex __x, float complex __z) __INTRODUCED_IN(26);
-long double complex cpowl(long double complex __x, long double complex __z) __INTRODUCED_IN(26);
+long double complex cpowl(long double complex __x, long double complex __z) __RENAME_LDBL(cpow, 26, 26);
/* 7.3.8.3 The csqrt functions */
double complex csqrt(double complex __z) __INTRODUCED_IN(23);
float complex csqrtf(float complex __z) __INTRODUCED_IN(23);
-long double complex csqrtl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23);
+long double complex csqrtl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(csqrt)*/;
/* 7.3.9 Manipulation functions */
/* 7.3.9.1 The carg functions */
double carg(double complex __z) __INTRODUCED_IN(23);
float cargf(float complex __z) __INTRODUCED_IN(23);
-long double cargl(long double complex __z) __INTRODUCED_IN(23);
+long double cargl(long double complex __z) __RENAME_LDBL(carg, 23, 23);
/* 7.3.9.2 The cimag functions */
double cimag(double complex __z) __INTRODUCED_IN(23);
float cimagf(float complex __z) __INTRODUCED_IN(23);
-long double cimagl(long double complex __z) __INTRODUCED_IN(23);
+long double cimagl(long double complex __z) __RENAME_LDBL(cimag, 23, 23);
/* 7.3.9.3 The conj functions */
double complex conj(double complex __z) __INTRODUCED_IN(23);
float complex conjf(float complex __z) __INTRODUCED_IN(23);
-long double complex conjl(long double complex __z) __INTRODUCED_IN(23);
+long double complex conjl(long double complex __z) __RENAME_LDBL(conj, 23, 23);
/* 7.3.9.4 The cproj functions */
double complex cproj(double complex __z) __INTRODUCED_IN(23);
float complex cprojf(float complex __z) __INTRODUCED_IN(23);
-long double complex cprojl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23);
+long double complex cprojl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(cproj)*/;
/* 7.3.9.5 The creal functions */
double creal(double complex __z) __INTRODUCED_IN(23);
float crealf(float complex __z) __INTRODUCED_IN(23);
-long double creall(long double complex __z) __INTRODUCED_IN(23);
+long double creall(long double complex __z) __RENAME_LDBL(creal, 23, 23);
__END_DECLS
diff --git a/libc/include/math.h b/libc/include/math.h
index 248ed3c..3d0ec49 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -22,19 +22,26 @@
__BEGIN_DECLS
-#define HUGE_VAL __builtin_huge_val()
+/* C11. */
-#define FP_ILOGB0 (-INT_MAX)
-#define FP_ILOGBNAN INT_MAX
+typedef double __double_t;
+typedef __double_t double_t;
+typedef float __float_t;
+typedef __float_t float_t;
-#define HUGE_VALF __builtin_huge_valf()
-#define HUGE_VALL __builtin_huge_vall()
-#define INFINITY __builtin_inff()
-#define NAN __builtin_nanf("")
+#define HUGE_VAL __builtin_huge_val()
+#define HUGE_VALF __builtin_huge_valf()
+#define HUGE_VALL __builtin_huge_vall()
-#define MATH_ERRNO 1
-#define MATH_ERREXCEPT 2
-#define math_errhandling MATH_ERREXCEPT
+#define INFINITY __builtin_inff()
+
+#define NAN __builtin_nanf("")
+
+#define FP_INFINITE 0x01
+#define FP_NAN 0x02
+#define FP_NORMAL 0x04
+#define FP_SUBNORMAL 0x08
+#define FP_ZERO 0x10
#if defined(__FP_FAST_FMA)
#define FP_FAST_FMA 1
@@ -46,20 +53,257 @@
#define FP_FAST_FMAL 1
#endif
-/* Symbolic constants to classify floating point numbers. */
-#define FP_INFINITE 0x01
-#define FP_NAN 0x02
-#define FP_NORMAL 0x04
-#define FP_SUBNORMAL 0x08
-#define FP_ZERO 0x10
-#define fpclassify(x) \
- __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
+#define FP_ILOGB0 (-INT_MAX)
+#define FP_ILOGBNAN INT_MAX
+
+#define MATH_ERRNO 1
+#define MATH_ERREXCEPT 2
+#define math_errhandling MATH_ERREXCEPT
+
+#define fpclassify(x) __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
#define isfinite(x) __builtin_isfinite(x)
+
#define isinf(x) __builtin_isinf(x)
+
#define isnan(x) __builtin_isnan(x)
+
#define isnormal(x) __builtin_isnormal(x)
+#define signbit(x) \
+ ((sizeof(x) == sizeof(float)) ? __builtin_signbitf(x) \
+ : (sizeof(x) == sizeof(double)) ? __builtin_signbit(x) \
+ : __builtin_signbitl(x))
+
+double acos(double __x);
+float acosf(float __x);
+long double acosl(long double __x) __RENAME_LDBL(acos, 3, 21);
+
+double asin(double __x);
+float asinf(float __x);
+long double asinl(long double __x) __RENAME_LDBL(asin, 3, 21);
+
+double atan(double __x);
+float atanf(float __x);
+long double atanl(long double __x) __RENAME_LDBL(atan, 3, 21);
+
+double atan2(double __y, double __x);
+float atan2f(float __y, float __x);
+long double atan2l(long double __y, long double __x) __RENAME_LDBL(atan2, 3, 21);
+
+double cos(double __x);
+float cosf(float __x);
+long double cosl(long double __x) __RENAME_LDBL(cos, 3, 21);
+
+double sin(double __x);
+float sinf(float __x);
+long double sinl(long double __x) __RENAME_LDBL(sin, 3, 21);
+
+double tan(double __x);
+float tanf(float __x);
+long double tanl(long double __x) __RENAME_LDBL(tan, 3, 21);
+
+double acosh(double __x);
+float acoshf(float __x);
+long double acoshl(long double __x) __RENAME_LDBL(acosh, 3, 21);
+
+double asinh(double __x);
+float asinhf(float __x);
+long double asinhl(long double __x) __RENAME_LDBL(asinh, 3, 21);
+
+double atanh(double __x);
+float atanhf(float __x);
+long double atanhl(long double __x) __RENAME_LDBL(atanh, 3, 21);
+
+double cosh(double __x);
+float coshf(float __x);
+long double coshl(long double __x) __RENAME_LDBL(cosh, 3, 21);
+
+double sinh(double __x);
+float sinhf(float __x);
+long double sinhl(long double __x) __RENAME_LDBL(sinh, 3, 21);
+
+double tanh(double __x);
+float tanhf(float __x);
+long double tanhl(long double __x) __RENAME_LDBL(tanh, 3, 21);
+
+double exp(double __x);
+float expf(float __x);
+long double expl(long double __x) __RENAME_LDBL(exp, 3, 21);
+
+double exp2(double __x);
+float exp2f(float __x);
+long double exp2l(long double __x) __RENAME_LDBL(exp2, 3, 21);
+
+double expm1(double __x);
+float expm1f(float __x);
+long double expm1l(long double __x) __RENAME_LDBL(expm1, 3, 21);
+
+double frexp(double __x, int* __exponent);
+float frexpf(float __x, int* __exponent);
+long double frexpl(long double __x, int* __exponent) __RENAME_LDBL(frexp, 3, 21);
+
+int ilogb(double __x) __attribute_const__;
+int ilogbf(float __x) __attribute_const__;
+int ilogbl(long double __x) __attribute_const__ __RENAME_LDBL(ilogb, 3, 3);
+
+double ldexp(double __x, int __exponent);
+float ldexpf(float __x, int __exponent);
+long double ldexpl(long double __x, int __exponent) __RENAME_LDBL(ldexp, 3, 3);
+
+double log(double __x);
+float logf(float __x);
+long double logl(long double __x) __RENAME_LDBL(log, 3, 21);
+
+double log10(double __x);
+float log10f(float __x);
+long double log10l(long double __x) __RENAME_LDBL(log10, 3, 21);
+
+double log1p(double __x);
+float log1pf(float __x);
+long double log1pl(long double __x) __RENAME_LDBL(log1p, 3, 21);
+
+double log2(double __x) __INTRODUCED_IN(18);
+float log2f(float __x) __INTRODUCED_IN(18);
+long double log2l(long double __x) __RENAME_LDBL(log2, 18, 18);
+
+double logb(double __x);
+float logbf(float __x);
+long double logbl(long double __x) __RENAME_LDBL(logb, 3, 18);
+
+double modf(double __x, double* __integral_part);
+float modff(float __x, float* __integral_part);
+long double modfl(long double __x, long double* __integral_part) __RENAME_LDBL(modf, 3, 21);
+
+double scalbn(double __x, int __exponent);
+float scalbnf(float __x, int __exponent);
+long double scalbnl(long double __x, int __exponent) __RENAME_LDBL(scalbn, 3, 3);
+
+/* TODO: once the NDK only supports >= 18, use __RENAME_LDBL here too. */
+double scalbln(double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
+float scalblnf(float __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
+long double scalblnl(long double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
+
+double cbrt(double __x);
+float cbrtf(float __x);
+long double cbrtl(long double __x) __RENAME_LDBL(cbrt, 3, 21);
+
+double fabs(double __x) __attribute_const__;
+float fabsf(float __x) __attribute_const__;
+long double fabsl(long double __x) __attribute_const__ __RENAME_LDBL(fabs, 3, 3);
+
+double hypot(double __x, double __y);
+float hypotf(float __x, float __y);
+long double hypotl(long double __x, long double __y) __RENAME_LDBL(hypot, 3, 21);
+
+double pow(double __x, double __y);
+float powf(float __x, float __y);
+long double powl(long double __x, long double __y) __RENAME_LDBL(pow, 3, 21);
+
+double sqrt(double __x);
+float sqrtf(float __x);
+long double sqrtl(long double __x) __RENAME_LDBL(sqrt, 3, 21);
+
+double erf(double __x);
+float erff(float __x);
+long double erfl(long double __x) __RENAME_LDBL(erf, 3, 21);
+
+double erfc(double __x);
+float erfcf(float __x);
+long double erfcl(long double __x) __RENAME_LDBL(erfc, 3, 21);
+
+double lgamma(double __x);
+float lgammaf(float __x);
+long double lgammal(long double __x) __RENAME_LDBL(lgamma, 3, 21);
+
+double tgamma(double __x);
+float tgammaf(float __x) __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13) __INTRODUCED_IN_X86(9);
+long double tgammal(long double __x) __RENAME_LDBL(tgamma, 3, 21);
+
+double ceil(double __x);
+float ceilf(float __x);
+long double ceill(long double __x) __RENAME_LDBL(ceil, 3, 3);
+
+double floor(double __x);
+float floorf(float __x);
+long double floorl(long double __x) __RENAME_LDBL(floor, 3, 3);
+
+double nearbyint(double __x);
+float nearbyintf(float __x);
+long double nearbyintl(long double __x) __RENAME_LDBL(nearbyint, 3, 21);
+
+double rint(double __x);
+float rintf(float __x);
+long double rintl(long double __x) __RENAME_LDBL(rint, 3, 21);
+
+long lrint(double __x);
+long lrintf(float __x);
+long lrintl(long double __x) __RENAME_LDBL(lrint, 3, 21);
+
+long long llrint(double __x);
+long long llrintf(float __x);
+long long llrintl(long double __x) __RENAME_LDBL(llrint, 3, 21);
+
+double round(double __x);
+float roundf(float __x);
+long double roundl(long double __x) __RENAME_LDBL(roundl, 3, 3);
+
+long lround(double __x);
+long lroundf(float __x);
+long lroundl(long double __x) __RENAME_LDBL(lround, 3, 3);
+
+long long llround(double __x);
+long long llroundf(float __x);
+long long llroundl(long double __x) __RENAME_LDBL(llround, 3, 3);
+
+double trunc(double __x);
+float truncf(float __x);
+long double truncl(long double __x) __RENAME_LDBL(trunc, 3, 3);
+
+double fmod(double __x, double __y);
+float fmodf(float __x, float __y);
+long double fmodl(long double __x, long double __y) __RENAME_LDBL(fmod, 3, 21);
+
+double remainder(double __x, double __y);
+float remainderf(float __x, float __y);
+long double remainderl(long double __x, long double __y) __RENAME_LDBL(remainder, 3, 21);
+
+double remquo(double __x, double __y, int* __quotient_bits);
+float remquof(float __x, float __y, int* __quotient_bits);
+long double remquol(long double __x, long double __y, int* __quotient_bits) __RENAME_LDBL(remquo, 3, 21);
+
+double copysign(double __value, double __sign) __attribute_const__;
+float copysignf(float __value, float __sign) __attribute_const__;
+long double copysignl(long double __value, long double __sign) __attribute_const__ __RENAME_LDBL(copysign, 3, 3);
+
+double nan(const char* __kind) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13) __INTRODUCED_IN_X86(9);
+float nanf(const char* __kind) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13) __INTRODUCED_IN_X86(9);
+long double nanl(const char* __kind) __attribute_const__ __RENAME_LDBL(nan, 13, 13);
+
+double nextafter(double __x, double __y);
+float nextafterf(float __x, float __y);
+long double nextafterl(long double __x, long double __y) __RENAME_LDBL(nextafter, 3, 21) __VERSIONER_NO_GUARD;
+
+double nexttoward(double __x, long double __y) __INTRODUCED_IN(18) __VERSIONER_NO_GUARD;
+float nexttowardf(float __x, long double __y);
+long double nexttowardl(long double __x, long double __y) __RENAME_LDBL(nexttoward, 18, 18) __VERSIONER_NO_GUARD;
+
+double fdim(double __x, double __y);
+float fdimf(float __x, float __y);
+long double fdiml(long double __x, long double __y) __RENAME_LDBL(fdim, 3, 3);
+
+double fmax(double __x, double __y) __attribute_const__;
+float fmaxf(float __x, float __y) __attribute_const__;
+long double fmaxl(long double __x, long double __y) __attribute_const__ __RENAME_LDBL(fmax, 3, 3);
+
+double fmin(double __x, double __y) __attribute_const__;
+float fminf(float __x, float __y) __attribute_const__;
+long double fminl(long double __x, long double __y) __attribute_const__ __RENAME_LDBL(fmin, 3, 3);
+
+double fma(double __x, double __y, double __z);
+float fmaf(float __x, float __y, float __z);
+long double fmal(long double __x, long double __y, long double __z) __RENAME_LDBL(fma, 3, 21) __VERSIONER_NO_GUARD;
+
#define isgreater(x, y) __builtin_isgreater((x), (y))
#define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y))
#define isless(x, y) __builtin_isless((x), (y))
@@ -67,92 +311,6 @@
#define islessgreater(x, y) __builtin_islessgreater((x), (y))
#define isunordered(x, y) __builtin_isunordered((x), (y))
-#define signbit(x) \
- ((sizeof(x) == sizeof(float)) ? __builtin_signbitf(x) \
- : (sizeof(x) == sizeof(double)) ? __builtin_signbit(x) \
- : __builtin_signbitl(x))
-
-typedef double __double_t;
-typedef __double_t double_t;
-typedef float __float_t;
-typedef __float_t float_t;
-
-#if defined(__USE_BSD)
-#define HUGE MAXFLOAT
-#endif
-
-extern int signgam;
-
-/*
- * Most of these functions depend on the rounding mode and have the side
- * effect of raising floating-point exceptions, so they are not declared
- * as __attribute_const__. In C99, FENV_ACCESS affects the purity of these functions.
- */
-
-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 __isnormalf(float __x) __attribute_const__;
-int __isnormal(double __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__;
-
-double acos(double __x);
-double asin(double __x);
-double atan(double __x);
-double atan2(double __y, double __x);
-double cos(double __x);
-double sin(double __x);
-double tan(double __x);
-
-double cosh(double __x);
-double sinh(double __x);
-double tanh(double __x);
-
-double exp(double __x);
-double frexp(double __x, int* __exponent); /* fundamentally !__attribute_const__ */
-double ldexp(double __x, int __exponent);
-double log(double __x);
-double log10(double __x);
-double modf(double __x, double* __integral_part); /* fundamentally !__attribute_const__ */
-
-double pow(double __x, double __y);
-double sqrt(double __x);
-
-double ceil(double __x);
-double fabs(double __x) __attribute_const__;
-double floor(double __x);
-double fmod(double __x, double __y);
-
-double acosh(double __x);
-double asinh(double __x);
-double atanh(double __x);
-double cbrt(double __x);
-double erf(double __x);
-double erfc(double __x);
-double exp2(double __x);
-double expm1(double __x);
-double fma(double __x, double __y, double __z);
-double hypot(double __x, double __y);
-int ilogb(double __x) __attribute_const__;
-double lgamma(double __x);
-long long llrint(double __x);
-long long llround(double __x);
-double log1p(double __x);
-double log2(double __x) __INTRODUCED_IN(18);
-double logb(double __x);
-long lrint(double __x);
-long lround(double __x);
-
/*
* https://code.google.com/p/android/issues/detail?id=271629
* To be fully compliant with C++, we need to not define these (C doesn't
@@ -167,150 +325,9 @@
int (isinf)(double __x) __attribute_const__ __INTRODUCED_IN(21);
int (isnan)(double __x) __attribute_const__;
-double nan(const char* __kind) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13)
- __INTRODUCED_IN_X86(9);
+/* POSIX extensions. */
-double nextafter(double __x, double __y);
-double remainder(double __x, double __y);
-double remquo(double __x, double __y, int* __quotient_bits);
-double rint(double __x);
-
-double copysign(double __value, double __sign) __attribute_const__;
-double fdim(double __x, double __y);
-double fmax(double __x, double __y) __attribute_const__;
-double fmin(double __x, double __y) __attribute_const__;
-double nearbyint(double __x);
-double round(double __x);
-double scalbln(double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
-double scalbn(double __x, int __exponent);
-double tgamma(double __x);
-double trunc(double __x);
-
-float acosf(float __x);
-float asinf(float __x);
-float atanf(float __x);
-float atan2f(float __y, float __x);
-float cosf(float __x);
-float sinf(float __x);
-float tanf(float __x);
-
-float coshf(float __x);
-float sinhf(float __x);
-float tanhf(float __x);
-
-float exp2f(float __x);
-float expf(float __x);
-float expm1f(float __x);
-float frexpf(float __x, int* __exponent); /* fundamentally !__attribute_const__ */
-int ilogbf(float __x) __attribute_const__;
-float ldexpf(float __x, int __exponent);
-float log10f(float __x);
-float log1pf(float __x);
-float log2f(float __x) __INTRODUCED_IN(18);
-float logf(float __x);
-float modff(float __x, float* __integral_part); /* fundamentally !__attribute_const__ */
-
-float powf(float __x, float __y);
-float sqrtf(float __x);
-
-float ceilf(float __x);
-float fabsf(float __x) __attribute_const__;
-float floorf(float __x);
-float fmodf(float __x, float __y);
-float roundf(float __x);
-
-float erff(float __x);
-float erfcf(float __x);
-float hypotf(float __x, float __y);
-float lgammaf(float __x);
-float tgammaf(float __x) __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13) __INTRODUCED_IN_X86(9);
-
-float acoshf(float __x);
-float asinhf(float __x);
-float atanhf(float __x);
-float cbrtf(float __x);
-float logbf(float __x);
-float copysignf(float __value, float __sign) __attribute_const__;
-long long llrintf(float __x);
-long long llroundf(float __x);
-long lrintf(float __x);
-long lroundf(float __x);
-float nanf(const char* __kind) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13)
- __INTRODUCED_IN_X86(9);
-float nearbyintf(float __x);
-float nextafterf(float __x, float __y);
-float remainderf(float __x, float __y);
-float remquof(float __x, float __y, int* __quotient_bits);
-float rintf(float __x);
-float scalblnf(float __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
-float scalbnf(float __x, int __exponent);
-float truncf(float __x);
-
-float fdimf(float __x, float __y);
-float fmaf(float __x, float __y, float __z);
-float fmaxf(float __x, float __y) __attribute_const__;
-float fminf(float __x, float __y) __attribute_const__;
-
-long double acoshl(long double __x) __INTRODUCED_IN(21);
-long double acosl(long double __x) __INTRODUCED_IN(21);
-long double asinhl(long double __x) __INTRODUCED_IN(21);
-long double asinl(long double __x) __INTRODUCED_IN(21);
-long double atan2l(long double __y, long double __x) __INTRODUCED_IN(21);
-long double atanhl(long double __x) __INTRODUCED_IN(21);
-long double atanl(long double __x) __INTRODUCED_IN(21);
-long double cbrtl(long double __x) __INTRODUCED_IN(21);
-long double ceill(long double __x);
-long double copysignl(long double __value, long double __sign) __attribute_const__;
-long double coshl(long double __x) __INTRODUCED_IN(21);
-long double cosl(long double __x) __INTRODUCED_IN(21);
-long double erfcl(long double __x) __INTRODUCED_IN(21);
-long double erfl(long double __x) __INTRODUCED_IN(21);
-long double exp2l(long double __x) __INTRODUCED_IN(21);
-long double expl(long double __x) __INTRODUCED_IN(21);
-long double expm1l(long double __x) __INTRODUCED_IN(21);
-long double fabsl(long double __x) __attribute_const__;
-long double fdiml(long double __x, long double __y);
-long double floorl(long double __x);
-long double fmal(long double __x, long double __y, long double __z) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
-long double fmaxl(long double __x, long double __y) __attribute_const__;
-long double fminl(long double __x, long double __y) __attribute_const__;
-long double fmodl(long double __x, long double __y) __INTRODUCED_IN(21);
-long double frexpl(long double __x, int* __exponent)
- __INTRODUCED_IN(21) __VERSIONER_NO_GUARD; /* fundamentally !__attribute_const__ */
-long double hypotl(long double __x, long double __y) __INTRODUCED_IN(21);
-int ilogbl(long double __x) __attribute_const__;
-long double ldexpl(long double __x, int __exponent);
-long double lgammal(long double __x) __INTRODUCED_IN(21);
-long long llrintl(long double __x) __INTRODUCED_IN(21);
-long long llroundl(long double __x);
-long double log10l(long double __x) __INTRODUCED_IN(21);
-long double log1pl(long double __x) __INTRODUCED_IN(21);
-long double log2l(long double __x) __INTRODUCED_IN(18);
-long double logbl(long double __x) __INTRODUCED_IN(18);
-long double logl(long double __x) __INTRODUCED_IN(21);
-long lrintl(long double __x) __INTRODUCED_IN(21);
-long lroundl(long double __x);
-long double modfl(long double __x, long double* __integral_part) __INTRODUCED_IN(21); /* fundamentally !__attribute_const__ */
-long double nanl(const char* __kind) __attribute_const__ __INTRODUCED_IN(13);
-long double nearbyintl(long double __x) __INTRODUCED_IN(21);
-long double nextafterl(long double __x, long double __y) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
-double nexttoward(double __x, long double __y) __INTRODUCED_IN(18) __VERSIONER_NO_GUARD;
-float nexttowardf(float __x, long double __y);
-long double nexttowardl(long double __x, long double __y) __INTRODUCED_IN(18) __VERSIONER_NO_GUARD;
-long double powl(long double __x, long double __y) __INTRODUCED_IN(21);
-long double remainderl(long double __x, long double __y) __INTRODUCED_IN(21);
-long double remquol(long double __x, long double __y, int* __quotient_bits) __INTRODUCED_IN(21);
-long double rintl(long double __x) __INTRODUCED_IN(21);
-long double roundl(long double __x);
-long double scalblnl(long double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
-long double scalbnl(long double __x, int __exponent);
-long double sinhl(long double __x) __INTRODUCED_IN(21);
-long double sinl(long double __x) __INTRODUCED_IN(21);
-long double sqrtl(long double __x) __INTRODUCED_IN(21);
-long double tanhl(long double __x) __INTRODUCED_IN(21);
-long double tanl(long double __x) __INTRODUCED_IN(21);
-long double tgammal(long double __x) __INTRODUCED_IN(21);
-long double truncl(long double __x);
+extern int signgam;
double j0(double __x);
double j1(double __x);
@@ -335,6 +352,38 @@
#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)
+#define HUGE MAXFLOAT
+#endif
+
+/* Extensions in both BSD and GNU. */
+
#if defined(__USE_BSD) || defined(__USE_GNU)
double gamma(double __x);
double scalb(double __x, double __exponent);
@@ -361,6 +410,8 @@
float significandf(float __x);
#endif
+/* GNU extensions. */
+
#if defined(__USE_GNU)
#define M_El 2.718281828459045235360287471352662498L /* e */
#define M_LOG2El 1.442695040888963407359924681001892137L /* log 2e */
diff --git a/libc/include/search.h b/libc/include/search.h
index 0015699..5930bcd 100644
--- a/libc/include/search.h
+++ b/libc/include/search.h
@@ -13,18 +13,26 @@
#include <sys/types.h>
typedef enum {
+ FIND,
+ ENTER
+} ACTION;
+
+typedef struct entry {
+ char* key;
+ void* data;
+} ENTRY;
+
+typedef enum {
preorder,
postorder,
endorder,
leaf
} VISIT;
-#ifdef _SEARCH_PRIVATE
-typedef struct node {
- char* key;
- struct node* llink;
- struct node* rlink;
-} node_t;
+#if defined(__USE_BSD) || defined(__USE_GNU)
+struct hsearch_data {
+ struct __hsearch* __hsearch;
+};
#endif
__BEGIN_DECLS
@@ -32,6 +40,16 @@
void insque(void* __element, void* __previous) __INTRODUCED_IN(21);
void remque(void* __element) __INTRODUCED_IN(21);
+int hcreate(size_t) __INTRODUCED_IN_FUTURE;
+void hdestroy(void) __INTRODUCED_IN_FUTURE;
+ENTRY* hsearch(ENTRY, ACTION) __INTRODUCED_IN_FUTURE;
+
+#if defined(__USE_BSD) || defined(__USE_GNU)
+int hcreate_r(size_t, struct hsearch_data*) __INTRODUCED_IN_FUTURE;
+void hdestroy_r(struct hsearch_data*) __INTRODUCED_IN_FUTURE;
+int hsearch_r(ENTRY, ACTION, ENTRY**, struct hsearch_data*) __INTRODUCED_IN_FUTURE;
+#endif
+
void* lfind(const void* __key, const void* __base, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*))
__INTRODUCED_IN(21);
void* lsearch(const void* __key, void* __base, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*))
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 4182f2d..86336a0 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -75,7 +75,7 @@
int posix_memalign(void** __memptr, size_t __alignment, size_t __size) __INTRODUCED_IN(16);
double strtod(const char* __s, char** __end_ptr);
-long double strtold(const char* __s, char** __end_ptr) __INTRODUCED_IN(21);
+long double strtold(const char* __s, char** __end_ptr) __RENAME_LDBL(strtod, 3, 21);
unsigned long strtoul_l(const char* __s, char** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(26);
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 58eebc5..063b51d 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -37,6 +37,11 @@
#ifndef _SYS_CDEFS_H_
#define _SYS_CDEFS_H_
+#include <android/api-level.h>
+#include <android/versioning.h>
+
+#define __BIONIC__ 1
+
/*
* Testing against Clang-specific extensions.
*/
@@ -219,8 +224,21 @@
#define __RENAME_IF_FILE_OFFSET64(func)
#endif
-#define __BIONIC__ 1
-#include <android/api-level.h>
+/*
+ * For LP32, `long double` == `double`. Historically many `long double` functions were incorrect
+ * on x86, missing on most architectures, and even if they are present and correct, linking to
+ * them just bloats your ELF file by adding extra relocations. The __BIONIC_LP32_USE_LONG_DOUBLE
+ * macro lets us test the headers both ways (and adds an escape valve).
+ *
+ * Note that some functions have their __RENAME_LDBL commented out as a sign that although we could
+ * use __RENAME_LDBL it would actually cause the function to be introduced later because the
+ * `long double` variant appeared before the `double` variant.
+ */
+#if defined(__LP64__) || defined(__BIONIC_LP32_USE_LONG_DOUBLE)
+#define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __INTRODUCED_IN(regular_api_level)
+#else
+#define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN(rewrite_api_level)
+#endif
/* glibc compatibility. */
#if defined(__LP64__)
@@ -334,8 +352,6 @@
/* Used to rename functions so that the compiler emits a call to 'x' rather than the function this was applied to. */
#define __RENAME(x) __asm__(#x)
-#include <android/versioning.h>
-
#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
#if defined(__LP64__)
#define __size_mul_overflow(a, b, result) __builtin_umull_overflow(a, b, result)
diff --git a/libc/include/sys/endian.h b/libc/include/sys/endian.h
index 799a6f2..9155b4c 100644
--- a/libc/include/sys/endian.h
+++ b/libc/include/sys/endian.h
@@ -45,7 +45,7 @@
#define __swap16 __builtin_bswap16
#define __swap32 __builtin_bswap32
-#define __swap64 __builtin_bswap64
+#define __swap64(x) __BIONIC_CAST(static_cast,uint64_t,__builtin_bswap64(x))
/* glibc compatibility. */
__BEGIN_DECLS
@@ -70,17 +70,17 @@
#define PDP_ENDIAN _PDP_ENDIAN
#define BYTE_ORDER _BYTE_ORDER
-#define NTOHL(x) (x) = ntohl((u_int32_t)(x))
-#define NTOHS(x) (x) = ntohs((u_int16_t)(x))
-#define HTONL(x) (x) = htonl((u_int32_t)(x))
-#define HTONS(x) (x) = htons((u_int16_t)(x))
+#define NTOHL(x) (x) = ntohl(__BIONIC_CAST(static_cast,u_int32_t,(x)))
+#define NTOHS(x) (x) = ntohs(__BIONIC_CAST(static_cast,u_int16_t,(x)))
+#define HTONL(x) (x) = htonl(__BIONIC_CAST(static_cast,u_int32_t,(x)))
+#define HTONS(x) (x) = htons(__BIONIC_CAST(static_cast,u_int16_t,(x)))
-#define htobe16 __swap16
-#define htobe32 __swap32
-#define htobe64 __swap64
-#define betoh16 __swap16
-#define betoh32 __swap32
-#define betoh64 __swap64
+#define htobe16(x) __swap16(x)
+#define htobe32(x) __swap32(x)
+#define htobe64(x) __swap64(x)
+#define betoh16(x) __swap16(x)
+#define betoh32(x) __swap32(x)
+#define betoh64(x) __swap64(x)
#define htole16(x) (x)
#define htole32(x) (x)
@@ -101,6 +101,7 @@
#define le16toh(x) htole16(x)
#define le32toh(x) htole32(x)
#define le64toh(x) htole64(x)
-#endif /* __USE_BSD */
+
+#endif
#endif
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 1dda4bd..1cf498c83 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -98,7 +98,7 @@
wchar_t* wcstok(wchar_t* __s, const wchar_t* __delimiter, wchar_t** __ptr);
long wcstol(const wchar_t* __s, wchar_t** __end_ptr, int __base);
long long wcstoll(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21);
-long double wcstold(const wchar_t* __s, wchar_t** __end_ptr) __INTRODUCED_IN(21);
+long double wcstold(const wchar_t* __s, wchar_t** __end_ptr) __RENAME_LDBL(wcstod, 3, 21);
unsigned long wcstoul(const wchar_t* __s, wchar_t** __end_ptr, int __base);
unsigned long long wcstoull(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21);
int wcswidth(const wchar_t* __s, size_t __n);
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index bca491b..fff80f6 100644
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
"""A glorified C pre-processor parser."""
import ctypes
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 31c2a53..5018951 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1323,6 +1323,12 @@
__freading; # future
__fwriting; # future
getlogin_r; # future
+ hcreate; # future
+ hcreate_r; # future
+ hdestroy; # future
+ hdestroy_r; # future
+ hsearch; # future
+ hsearch_r; # future
iconv; # future
iconv_close; # future
iconv_open; # future
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 6cc6d64..4ea5896 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1243,6 +1243,12 @@
__freading; # future
__fwriting; # future
getlogin_r; # future
+ hcreate; # future
+ hcreate_r; # future
+ hdestroy; # future
+ hdestroy_r; # future
+ hsearch; # future
+ hsearch_r; # future
iconv; # future
iconv_close; # future
iconv_open; # future
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 5cbfaeb..a0ac50a 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1348,6 +1348,12 @@
__freading; # future
__fwriting; # future
getlogin_r; # future
+ hcreate; # future
+ hcreate_r; # future
+ hdestroy; # future
+ hdestroy_r; # future
+ hsearch; # future
+ hsearch_r; # future
iconv; # future
iconv_close; # future
iconv_open; # future
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 34369ba..8970549 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1307,6 +1307,12 @@
__freading; # future
__fwriting; # future
getlogin_r; # future
+ hcreate; # future
+ hcreate_r; # future
+ hdestroy; # future
+ hdestroy_r; # future
+ hsearch; # future
+ hsearch_r; # future
iconv; # future
iconv_close; # future
iconv_open; # future
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 6cc6d64..4ea5896 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1243,6 +1243,12 @@
__freading; # future
__fwriting; # future
getlogin_r; # future
+ hcreate; # future
+ hcreate_r; # future
+ hdestroy; # future
+ hdestroy_r; # future
+ hsearch; # future
+ hsearch_r; # future
iconv; # future
iconv_close; # future
iconv_open; # future
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 76dffa5..5439852 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1305,6 +1305,12 @@
__freading; # future
__fwriting; # future
getlogin_r; # future
+ hcreate; # future
+ hcreate_r; # future
+ hdestroy; # future
+ hdestroy_r; # future
+ hsearch; # future
+ hsearch_r; # future
iconv; # future
iconv_close; # future
iconv_open; # future
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 6cc6d64..4ea5896 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1243,6 +1243,12 @@
__freading; # future
__fwriting; # future
getlogin_r; # future
+ hcreate; # future
+ hcreate_r; # future
+ hdestroy; # future
+ hdestroy_r; # future
+ hsearch; # future
+ hsearch_r; # future
iconv; # future
iconv_close; # future
iconv_open; # future
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index 752d507..65ae6fa 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -41,12 +41,12 @@
#include "debug_log.h"
#include "malloc_debug.h"
-static void EnableToggle(int, siginfo_t*, void*) {
- if (g_debug->backtrace->enabled()) {
- g_debug->backtrace->set_enabled(false);
- } else {
- g_debug->backtrace->set_enabled(true);
- }
+static void ToggleBacktraceEnable(int, siginfo_t*, void*) {
+ g_debug->backtrace->ToggleBacktraceEnabled();
+}
+
+static void EnableDump(int, siginfo_t*, void*) {
+ g_debug->backtrace->EnableDumping();
}
BacktraceData::BacktraceData(DebugData* debug_data, const Config& config, size_t* offset)
@@ -62,7 +62,7 @@
struct sigaction enable_act;
memset(&enable_act, 0, sizeof(enable_act));
- enable_act.sa_sigaction = EnableToggle;
+ enable_act.sa_sigaction = ToggleBacktraceEnable;
enable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&enable_act.sa_mask);
if (sigaction(config.backtrace_signal(), &enable_act, nullptr) != 0) {
@@ -72,5 +72,20 @@
info_log("%s: Run: 'kill -%d %d' to enable backtracing.", getprogname(),
config.backtrace_signal(), getpid());
}
+
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+
+ act.sa_sigaction = EnableDump;
+ act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+ sigemptyset(&act.sa_mask);
+ if (sigaction(config.backtrace_dump_signal(), &act, nullptr) != 0) {
+ error_log("Unable to set up backtrace dump signal function: %s", strerror(errno));
+ return false;
+ }
+ info_log("%s: Run: 'kill -%d %d' to dump the backtrace.", getprogname(),
+ config.backtrace_dump_signal(), getpid());
+
+ dump_ = false;
return true;
}
diff --git a/libc/malloc_debug/BacktraceData.h b/libc/malloc_debug/BacktraceData.h
index 6dee505..c8234dc 100644
--- a/libc/malloc_debug/BacktraceData.h
+++ b/libc/malloc_debug/BacktraceData.h
@@ -31,6 +31,8 @@
#include <stdint.h>
+#include <atomic>
+
#include <private/bionic_macros.h>
#include "OptionData.h"
@@ -47,13 +49,21 @@
inline size_t alloc_offset() { return alloc_offset_; }
- bool enabled() { return enabled_; }
- void set_enabled(bool enabled) { enabled_ = enabled; }
+ bool ShouldBacktrace() { return enabled_ == 1; }
+ void ToggleBacktraceEnabled() { enabled_.fetch_xor(1); }
+
+ void EnableDumping() { dump_ = true; }
+ bool ShouldDumpAndReset() {
+ bool expected = true;
+ return dump_.compare_exchange_strong(expected, false);
+ }
private:
size_t alloc_offset_ = 0;
- volatile bool enabled_ = false;
+ std::atomic_uint8_t enabled_;
+
+ std::atomic_bool dump_;
DISALLOW_COPY_AND_ASSIGN(BacktraceData);
};
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index df453a9..e3798ab 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -56,6 +56,7 @@
static constexpr size_t DEFAULT_BACKTRACE_FRAMES = 16;
static constexpr size_t MAX_BACKTRACE_FRAMES = 256;
+static constexpr const char DEFAULT_BACKTRACE_DUMP_PREFIX[] = "/data/local/tmp/backtrace_heap";
static constexpr size_t DEFAULT_EXPAND_BYTES = 16;
static constexpr size_t MAX_EXPAND_BYTES = 16384;
@@ -85,6 +86,13 @@
{BACKTRACE | TRACK_ALLOCS, &Config::SetBacktraceEnableOnSignal},
},
+ {"backtrace_dump_on_exit",
+ {0, &Config::SetBacktraceDumpOnExit},
+ },
+ {"backtrace_dump_prefix",
+ {0, &Config::SetBacktraceDumpPrefix},
+ },
+
{"fill",
{FILL_ON_ALLOC | FILL_ON_FREE, &Config::SetFill},
},
@@ -236,6 +244,24 @@
&backtrace_frames_);
}
+bool Config::SetBacktraceDumpOnExit(const std::string& option, const std::string& value) {
+ if (Config::VerifyValueEmpty(option, value)) {
+ backtrace_dump_on_exit_ = true;
+ return true;
+ }
+ return false;
+}
+
+bool Config::SetBacktraceDumpPrefix(const std::string&, const std::string& value) {
+ if (value.empty()) {
+ backtrace_dump_prefix_ = DEFAULT_BACKTRACE_DUMP_PREFIX;
+ } else {
+ backtrace_dump_prefix_ = value;
+ }
+ return true;
+}
+
+
bool Config::SetExpandAlloc(const std::string& option, const std::string& value) {
return ParseValue(option, value, DEFAULT_EXPAND_BYTES, 1, MAX_EXPAND_BYTES, &expand_alloc_bytes_);
}
@@ -309,6 +335,9 @@
error_log(" backtrace[=XX]");
error_log(" Enable capturing the backtrace at the point of allocation.");
error_log(" If XX is set it sets the number of backtrace frames.");
+ error_log(" This option also enables dumping the backtrace heap data");
+ error_log(" when a signal is received. The data is dumped to the file");
+ error_log(" backtrace_dump_prefix.<PID>.txt.");
error_log(" The default is %zu frames, the max number of frames is %zu.",
DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
error_log("");
@@ -319,6 +348,19 @@
error_log(" frames. The default is %zu frames, the max number of frames is %zu.",
DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
error_log("");
+ error_log(" backtrace_dump_prefix[=FILE]");
+ error_log(" This option only has meaning if the backtrace option has been specified.");
+ error_log(" This is the prefix of the name of the file to which backtrace heap");
+ error_log(" data will be dumped. The file will be named backtrace_dump_prefix.<PID>.txt.");
+ error_log(" The default is %s.", DEFAULT_BACKTRACE_DUMP_PREFIX);
+
+ error_log("");
+ error_log(" backtrace_dump_on_exit");
+ error_log(" This option only has meaning if the backtrace option has been specified.");
+ error_log(" This will cause all live allocations to be dumped to the file");
+ error_log(" backtrace_dump_prefix.<PID>.final.txt.");
+ error_log(" The default is false.");
+ error_log("");
error_log(" fill_on_alloc[=XX]");
error_log(" On first allocation, fill with the value 0x%02x.", DEFAULT_FILL_ALLOC_VALUE);
error_log(" If XX is set it will only fill up to XX bytes of the");
@@ -426,12 +468,15 @@
front_guard_value_ = DEFAULT_FRONT_GUARD_VALUE;
rear_guard_value_ = DEFAULT_REAR_GUARD_VALUE;
backtrace_signal_ = SIGRTMAX - 19;
+ backtrace_dump_signal_ = SIGRTMAX - 17;
record_allocs_signal_ = SIGRTMAX - 18;
free_track_backtrace_num_frames_ = 0;
record_allocs_file_.clear();
fill_on_free_bytes_ = 0;
backtrace_enable_on_signal_ = false;
backtrace_enabled_ = false;
+ backtrace_dump_on_exit_ = false;
+ backtrace_dump_prefix_ = DEFAULT_BACKTRACE_DUMP_PREFIX;
// Process each option name we can find.
std::string option;
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index d8a7069..349ad77 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -65,9 +65,12 @@
uint64_t options() const { return options_; }
int backtrace_signal() const { return backtrace_signal_; }
+ int backtrace_dump_signal() const { return backtrace_dump_signal_; }
size_t backtrace_frames() const { return backtrace_frames_; }
size_t backtrace_enabled() const { return backtrace_enabled_; }
size_t backtrace_enable_on_signal() const { return backtrace_enable_on_signal_; }
+ bool backtrace_dump_on_exit() const { return backtrace_dump_on_exit_; }
+ const std::string& backtrace_dump_prefix() const { return backtrace_dump_prefix_; }
size_t front_guard_bytes() const { return front_guard_bytes_; }
size_t rear_guard_bytes() const { return rear_guard_bytes_; }
@@ -110,6 +113,8 @@
bool SetBacktrace(const std::string& option, const std::string& value);
bool SetBacktraceEnableOnSignal(const std::string& option, const std::string& value);
+ bool SetBacktraceDumpOnExit(const std::string& option, const std::string& value);
+ bool SetBacktraceDumpPrefix(const std::string& option, const std::string& value);
bool SetExpandAlloc(const std::string& option, const std::string& value);
@@ -130,8 +135,11 @@
bool backtrace_enable_on_signal_ = false;
int backtrace_signal_ = 0;
+ int backtrace_dump_signal_ = 0;
bool backtrace_enabled_ = false;
size_t backtrace_frames_ = 0;
+ bool backtrace_dump_on_exit_ = false;
+ std::string backtrace_dump_prefix_;
size_t fill_on_alloc_bytes_ = 0;
size_t fill_on_free_bytes_ = 0;
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index 03a8a73..bb56cb8 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -108,6 +108,17 @@
This option adds a special header to all allocations that contains the
backtrace and information about the original allocation.
+As of P, this option will also enable dumping backtrace heap data to a
+file when the process receives the signal SIGRTMAX - 17 ( which is 47 on most
+Android devices). The format of this dumped data is the same format as
+that dumped when running am dumpheap -n. The default is to dump this data
+to the file /data/local/tmp/backtrace\_heap.**PID**.txt. This is useful when
+used with native only executables that run for a while since these processes
+are not spawned from a zygote process.
+
+Note that when the signal is received, the heap is not dumped until the next
+malloc/free occurs.
+
### backtrace\_enable\_on\_signal[=MAX\_FRAMES]
Enable capturing the backtrace of each allocation site. If the
backtrace capture is toggled when the process receives the signal
@@ -123,6 +134,26 @@
This option adds a special header to all allocations that contains the
backtrace and information about the original allocation.
+### backtrace\_dump\_on\_exit
+As of P, when the backtrace option has been enabled, this causes the backtrace
+dump heap data to be dumped to a file when the program exits. If the backtrace
+option has not been enabled, this does nothing. The default is to dump this
+to the file named /data/local/tmp/backtrace\_heap.**PID**.exit.txt.
+
+The file location can be changed by setting the backtrace\_dump\_prefix
+option.
+
+### backtrace\_dump\_prefix
+As of P, when the backtrace options has been enabled, this sets the prefix
+used for dumping files when the signal SIGRTMAX - 17 is received or when
+the program exits and backtrace\_dump\_on\_exit is set.
+
+The default is /data/local/tmp/backtrace\_heap.
+
+When this value is changed from the default, then the filename chosen
+on the signal will be backtrace\_dump\_prefix.**PID**.txt. The filename chosen
+when the program exits will be backtrace\_dump\_prefix.**PID**.exit.txt.
+
### fill\_on\_alloc[=MAX\_FILLED\_BYTES]
Any allocation routine, other than calloc, will result in the allocation being
filled with the value 0xeb. When doing a realloc to a larger size, the bytes
@@ -369,6 +400,66 @@
As with the other error message, the function in parenthesis is the
function that was called with the bad pointer.
+Backtrace Heap Dump Format
+==========================
+
+This section describes the format of the backtrace heap dump. This data is
+generated by am dumpheap -n or, as of P, by the signal or on exit.
+
+The data has this header:
+
+ Android Native Heap Dump v1.0
+
+ Total memory: XXXX
+ Allocation records: YYYY
+ Backtrace size: ZZZZ
+
+Total memory is the total of all of the currently live allocations.
+Allocation records is the total number of allocation records.
+Backtrace size is the maximum number of backtrace frames that can be present.
+
+Following this header are two different sections, the first section is the
+allocation records, the second section is the map data.
+
+The allocation record data has this format:
+
+ z ZYGOTE_CHILD_ALLOC sz ALLOCATION_SIZE num NUM_ALLOCATIONS bt FRAMES
+
+ZYGOTE\_CHILD\_ALLOC is either 0 or 1. 0 means this was allocated by the
+zygote process or in a process not spawned from the zygote. 1 means this
+was allocated by an application after it forked off from the zygote process.
+
+ALLOCATION\_SIZE is the size of the allocation.
+NUM\_ALLOCATIONS is the number of allocations that have this size and have the
+same backtrace.
+FRAMES is a list of instruction pointers that represent the backtrace of the
+allocation.
+
+Example:
+
+ z 0 sz 400 num 1 bt 0000a230 0000b500
+ z 1 sz 500 num 3 bt 0000b000 0000c000
+
+The first allocation record was created by the zygote of size 400 only one
+with this backtrace/size and a backtrace of 0xa230, 0xb500.
+The second allocation record was create by an application spawned from the
+zygote of size 500, where there are three of these allocation with the same
+backtrace/size and a backtrace of 0xb000, 0xc000.
+
+The final section is the map data for the process:
+
+ MAPS
+ 7fe9181000-7fe91a2000 rw-p 00000000 00:00 0 /system/lib/libc.so
+ .
+ .
+ .
+ END
+
+The map data is simply the output of /proc/PID/maps. This data can be used to
+decode the frames in the backtraces.
+
+There is a tool to visualize this data, development/scripts/native\_heapdump\_viewer.py.
+
Examples
========
diff --git a/libc/malloc_debug/TrackData.cpp b/libc/malloc_debug/TrackData.cpp
index 7ce477c..4266aa2 100644
--- a/libc/malloc_debug/TrackData.cpp
+++ b/libc/malloc_debug/TrackData.cpp
@@ -59,6 +59,49 @@
});
}
+void TrackData::GetListBySizeThenBacktrace(std::vector<const Header*>* list, size_t* total_memory) {
+ if (!(debug_->config().options() & BACKTRACE)) {
+ return;
+ }
+
+ *total_memory = 0;
+ for (const auto& header : headers_) {
+ list->push_back(header);
+ *total_memory += header->real_size();
+ }
+
+ // Put all zygote allocations first by size and backtrace.
+ // Then all zygote child allocation by size and backtrace.
+ std::sort(list->begin(), list->end(), [&](const Header* a, const Header* b) {
+ if (a->zygote_child_alloc() && !b->zygote_child_alloc()) {
+ return false;
+ } else if (!a->zygote_child_alloc() && b->zygote_child_alloc()) {
+ return true;
+ }
+ if (a->real_size() != b->real_size()) return a->real_size() < b->real_size();
+ // If the size is the same, compare backtrace elements.
+ BacktraceHeader* a_back = debug_->GetAllocBacktrace(a);
+ BacktraceHeader* b_back = debug_->GetAllocBacktrace(b);
+ for (size_t i = 0; i < a_back->num_frames; i++) {
+ if (i > b_back->num_frames) {
+ // All frames equal up to this point, but a has more frames available.
+ return false;
+ }
+ if (a_back->frames[i] < b_back->frames[i]) {
+ return false;
+ } else if (a_back->frames[i] > b_back->frames[i]) {
+ return true;
+ }
+ }
+ if (a_back->num_frames < b_back->num_frames) {
+ // All frames equal up to this point, but b has more frames available.
+ return true;
+ }
+ return false;
+ });
+
+}
+
void TrackData::Add(const Header* header, bool backtrace_found) {
pthread_mutex_lock(&mutex_);
if (backtrace_found) {
diff --git a/libc/malloc_debug/TrackData.h b/libc/malloc_debug/TrackData.h
index e4c8951..f7486e9 100644
--- a/libc/malloc_debug/TrackData.h
+++ b/libc/malloc_debug/TrackData.h
@@ -51,6 +51,8 @@
void GetList(std::vector<const Header*>* list);
+ void GetListBySizeThenBacktrace(std::vector<const Header*>* list, size_t* total_memory);
+
void Add(const Header* header, bool backtrace_found);
void Remove(const Header* header, bool backtrace_found);
diff --git a/libc/malloc_debug/exported32.map b/libc/malloc_debug/exported32.map
index 59bb102..e92a7cf 100644
--- a/libc/malloc_debug/exported32.map
+++ b/libc/malloc_debug/exported32.map
@@ -1,6 +1,7 @@
LIBC_MALLOC_DEBUG {
global:
debug_calloc;
+ debug_dump_heap;
debug_finalize;
debug_free;
debug_free_malloc_leak_info;
diff --git a/libc/malloc_debug/exported64.map b/libc/malloc_debug/exported64.map
index ec9d840..94104b0 100644
--- a/libc/malloc_debug/exported64.map
+++ b/libc/malloc_debug/exported64.map
@@ -1,6 +1,7 @@
LIBC_MALLOC_DEBUG {
global:
debug_calloc;
+ debug_dump_heap;
debug_finalize;
debug_free;
debug_free_malloc_leak_info;
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 014d385..d890a1c 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -34,8 +34,11 @@
#include <sys/param.h>
#include <unistd.h>
+#include <mutex>
#include <vector>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <private/bionic_malloc_dispatch.h>
#include "backtrace.h"
@@ -65,6 +68,7 @@
bool debug_initialize(const MallocDispatch* malloc_dispatch, int* malloc_zygote_child,
const char* options);
void debug_finalize();
+bool debug_dump_heap(const char* file_name);
void debug_get_malloc_leak_info(
uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory,
size_t* backtrace_size);
@@ -138,7 +142,7 @@
header->orig_pointer = orig_pointer;
header->size = size;
if (*g_malloc_zygote_child) {
- header->set_zygote();
+ header->set_zygote_child_alloc();
}
header->usable_size = g_dispatch->malloc_usable_size(orig_pointer);
if (header->usable_size == 0) {
@@ -164,7 +168,7 @@
bool backtrace_found = false;
if (g_debug->config().options() & BACKTRACE) {
BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
- if (g_debug->backtrace->enabled()) {
+ if (g_debug->backtrace->ShouldBacktrace()) {
back_header->num_frames = backtrace_get(
&back_header->frames[0], g_debug->config().backtrace_frames());
backtrace_found = back_header->num_frames > 0;
@@ -224,6 +228,13 @@
g_debug->track->DisplayLeaks();
}
+ if ((g_debug->config().options() & BACKTRACE) && g_debug->config().backtrace_dump_on_exit()) {
+ ScopedDisableDebugCalls disable;
+ debug_dump_heap(
+ android::base::StringPrintf("%s.%d.exit.txt",
+ g_debug->config().backtrace_dump_prefix().c_str(), getpid()).c_str());
+ }
+
DebugDisableSet(true);
backtrace_shutdown();
@@ -288,6 +299,13 @@
}
static void *internal_malloc(size_t size) {
+ if ((g_debug->config().options() & BACKTRACE) && g_debug->backtrace->ShouldDumpAndReset()) {
+ debug_dump_heap(
+ android::base::StringPrintf("%s.%d.txt",
+ g_debug->config().backtrace_dump_prefix().c_str(),
+ getpid()).c_str());
+ }
+
if (size == 0) {
size = 1;
}
@@ -341,6 +359,13 @@
}
static void internal_free(void* pointer) {
+ if ((g_debug->config().options() & BACKTRACE) && g_debug->backtrace->ShouldDumpAndReset()) {
+ debug_dump_heap(
+ android::base::StringPrintf("%s.%d.txt",
+ g_debug->config().backtrace_dump_prefix().c_str(),
+ getpid()).c_str());
+ }
+
void* free_pointer = pointer;
size_t bytes;
Header* header;
@@ -538,7 +563,7 @@
if (real_size < header->usable_size) {
header->size = real_size;
if (*g_malloc_zygote_child) {
- header->set_zygote();
+ header->set_zygote_child_alloc();
}
if (g_debug->config().options() & REAR_GUARD) {
// Don't bother allocating a smaller pointer in this case, simply
@@ -758,3 +783,65 @@
return debug_memalign(getpagesize(), size);
}
#endif
+
+static std::mutex g_dump_lock;
+
+bool debug_dump_heap(const char* file_name) {
+ ScopedDisableDebugCalls disable;
+
+ std::lock_guard<std::mutex> guard(g_dump_lock);
+
+ FILE* fp = fopen(file_name, "w+e");
+ if (fp == nullptr) {
+ error_log("Unable to create file: %s", file_name);
+ return false;
+ }
+ error_log("Dumping to file: %s\n", file_name);
+
+ if (!(g_debug->config().options() & BACKTRACE)) {
+ fprintf(fp, "Native heap dump not available. To enable, run these commands (requires root):\n");
+ fprintf(fp, "# adb shell stop\n");
+ fprintf(fp, "# adb shell setprop libc.debug.malloc.options backtrace\n");
+ fprintf(fp, "# adb shell start\n");
+ fclose(fp);
+ return false;
+ }
+
+ fprintf(fp, "Android Native Heap Dump v1.0\n\n");
+
+ std::vector<const Header*> list;
+ size_t total_memory;
+ g_debug->track->GetListBySizeThenBacktrace(&list, &total_memory);
+ fprintf(fp, "Total memory: %zu\n", total_memory);
+ fprintf(fp, "Allocation records: %zd\n", list.size());
+ fprintf(fp, "Backtrace size: %zu\n", g_debug->config().backtrace_frames());
+ fprintf(fp, "\n");
+
+ for (const auto& header : list) {
+ const BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
+ fprintf(fp, "z %d sz %8zu num 1 bt", (header->zygote_child_alloc()) ? 1 : 0,
+ header->real_size());
+ for (size_t i = 0; i < back_header->num_frames; i++) {
+ if (back_header->frames[i] == 0) {
+ break;
+ }
+#ifdef __LP64__
+ fprintf(fp, " %016" PRIxPTR, back_header->frames[i]);
+#else
+ fprintf(fp, " %08" PRIxPTR, back_header->frames[i]);
+#endif
+ }
+ fprintf(fp, "\n");
+ }
+
+ fprintf(fp, "MAPS\n");
+ std::string content;
+ if (!android::base::ReadFileToString("/proc/self/maps", &content)) {
+ fprintf(fp, "Could not open /proc/self/maps\n");
+ } else {
+ fprintf(fp, "%s", content.c_str());
+ }
+ fprintf(fp, "END\n");
+ fclose(fp);
+ return true;
+}
diff --git a/libc/malloc_debug/malloc_debug.h b/libc/malloc_debug/malloc_debug.h
index 347fae2..4a1e8da 100644
--- a/libc/malloc_debug/malloc_debug.h
+++ b/libc/malloc_debug/malloc_debug.h
@@ -54,7 +54,8 @@
size_t size;
size_t usable_size;
size_t real_size() const { return size & ~(1U << 31); }
- void set_zygote() { size |= 1U << 31; }
+ void set_zygote_child_alloc() { size |= 1U << 31; }
+ bool zygote_child_alloc() const { return size & (1U << 31); }
static size_t max_size() { return (1U << 31) - 1; }
} __attribute__((packed));
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index 77dc848..ee8fe06 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -60,6 +60,9 @@
"6 malloc_debug backtrace[=XX]\n"
"6 malloc_debug Enable capturing the backtrace at the point of allocation.\n"
"6 malloc_debug If XX is set it sets the number of backtrace frames.\n"
+ "6 malloc_debug This option also enables dumping the backtrace heap data\n"
+ "6 malloc_debug when a signal is received. The data is dumped to the file\n"
+ "6 malloc_debug backtrace_dump_prefix.<PID>.txt.\n"
"6 malloc_debug The default is 16 frames, the max number of frames is 256.\n"
"6 malloc_debug \n"
"6 malloc_debug backtrace_enable_on_signal[=XX]\n"
@@ -68,6 +71,18 @@
"6 malloc_debug receives a signal. If XX is set it sets the number of backtrace\n"
"6 malloc_debug frames. The default is 16 frames, the max number of frames is 256.\n"
"6 malloc_debug \n"
+ "6 malloc_debug backtrace_dump_prefix[=FILE]\n"
+ "6 malloc_debug This option only has meaning if the backtrace option has been specified.\n"
+ "6 malloc_debug This is the prefix of the name of the file to which backtrace heap\n"
+ "6 malloc_debug data will be dumped. The file will be named backtrace_dump_prefix.<PID>.txt.\n"
+ "6 malloc_debug The default is /data/local/tmp/backtrace_heap.\n"
+ "6 malloc_debug \n"
+ "6 malloc_debug backtrace_dump_on_exit\n"
+ "6 malloc_debug This option only has meaning if the backtrace option has been specified.\n"
+ "6 malloc_debug This will cause all live allocations to be dumped to the file\n"
+ "6 malloc_debug backtrace_dump_prefix.<PID>.final.txt.\n"
+ "6 malloc_debug The default is false.\n"
+ "6 malloc_debug \n"
"6 malloc_debug fill_on_alloc[=XX]\n"
"6 malloc_debug On first allocation, fill with the value 0xeb.\n"
"6 malloc_debug If XX is set it will only fill up to XX bytes of the\n"
@@ -292,12 +307,14 @@
ASSERT_EQ(64U, config->backtrace_frames());
ASSERT_TRUE(config->backtrace_enabled());
ASSERT_FALSE(config->backtrace_enable_on_signal());
+ ASSERT_FALSE(config->backtrace_dump_on_exit());
ASSERT_TRUE(InitConfig("backtrace")) << getFakeLogPrint();
ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
ASSERT_EQ(16U, config->backtrace_frames());
ASSERT_TRUE(config->backtrace_enabled());
ASSERT_FALSE(config->backtrace_enable_on_signal());
+ ASSERT_FALSE(config->backtrace_dump_on_exit());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -309,12 +326,14 @@
ASSERT_EQ(64U, config->backtrace_frames());
ASSERT_FALSE(config->backtrace_enabled());
ASSERT_TRUE(config->backtrace_enable_on_signal());
+ ASSERT_FALSE(config->backtrace_dump_on_exit());
ASSERT_TRUE(InitConfig("backtrace_enable_on_signal")) << getFakeLogPrint();
ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
ASSERT_EQ(16U, config->backtrace_frames());
ASSERT_FALSE(config->backtrace_enabled());
ASSERT_TRUE(config->backtrace_enable_on_signal());
+ ASSERT_FALSE(config->backtrace_dump_on_exit());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -326,12 +345,14 @@
ASSERT_EQ(64U, config->backtrace_frames());
ASSERT_FALSE(config->backtrace_enabled());
ASSERT_TRUE(config->backtrace_enable_on_signal());
+ ASSERT_FALSE(config->backtrace_dump_on_exit());
ASSERT_TRUE(InitConfig("backtrace")) << getFakeLogPrint();
ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
ASSERT_EQ(16U, config->backtrace_frames());
ASSERT_TRUE(config->backtrace_enabled());
ASSERT_FALSE(config->backtrace_enable_on_signal());
+ ASSERT_FALSE(config->backtrace_dump_on_exit());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -343,12 +364,46 @@
ASSERT_EQ(16U, config->backtrace_frames());
ASSERT_TRUE(config->backtrace_enabled());
ASSERT_TRUE(config->backtrace_enable_on_signal());
+ ASSERT_FALSE(config->backtrace_dump_on_exit());
ASSERT_TRUE(InitConfig("backtrace backtrace_enable_on_signal")) << getFakeLogPrint();
ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
ASSERT_EQ(16U, config->backtrace_frames());
ASSERT_TRUE(config->backtrace_enabled());
ASSERT_TRUE(config->backtrace_enable_on_signal());
+ ASSERT_FALSE(config->backtrace_dump_on_exit());
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_dump_on_exit) {
+ ASSERT_TRUE(InitConfig("backtrace_dump_on_exit")) << getFakeLogPrint();
+ ASSERT_EQ(0U, config->options());
+ ASSERT_TRUE(config->backtrace_dump_on_exit());
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_dump_on_exit_error) {
+ ASSERT_FALSE(InitConfig("backtrace_dump_on_exit=something")) << getFakeLogPrint();
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string log_msg(
+ "6 malloc_debug malloc_testing: value set for option 'backtrace_dump_on_exit' "
+ "which does not take a value\n");
+ ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_dump_prefix) {
+ ASSERT_TRUE(InitConfig("backtrace_dump_prefix")) << getFakeLogPrint();
+ ASSERT_EQ(0U, config->options());
+ ASSERT_EQ("/data/local/tmp/backtrace_heap", config->backtrace_dump_prefix());
+
+ ASSERT_TRUE(InitConfig("backtrace_dump_prefix=/fake/location")) << getFakeLogPrint();
+ ASSERT_EQ(0U, config->options());
+ ASSERT_EQ("/fake/location", config->backtrace_dump_prefix());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 4fdba2e..37d8057 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -32,6 +32,7 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <private/bionic_macros.h>
#include <private/bionic_malloc_dispatch.h>
@@ -82,6 +83,8 @@
static constexpr const char RECORD_ALLOCS_FILE[] = "/data/local/tmp/record_allocs.txt";
+static constexpr const char BACKTRACE_DUMP_PREFIX[] = "/data/local/tmp/backtrace_heap";
+
class MallocDebugTest : public ::testing::Test {
protected:
void SetUp() override {
@@ -104,6 +107,8 @@
initialized = true;
}
+ void BacktraceDumpOnSignal(bool trigger_with_alloc);
+
bool initialized;
int zygote;
@@ -132,7 +137,7 @@
mallopt,
};
-void VerifyAllocCalls() {
+void VerifyAllocCalls(bool backtrace_enabled) {
size_t alloc_size = 1024;
// Verify debug_malloc.
@@ -186,17 +191,23 @@
ASSERT_TRUE(pointer == nullptr);
ASSERT_STREQ("", getFakeLogBuf().c_str());
- ASSERT_STREQ("", getFakeLogPrint().c_str());
+ std::string expected_log;
+ if (backtrace_enabled) {
+ expected_log += android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
+ }
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
TEST_F(MallocDebugTest, fill_generic) {
Init("fill");
- VerifyAllocCalls();
+ VerifyAllocCalls(false);
}
TEST_F(MallocDebugTest, fill_on_alloc_generic) {
Init("fill_on_alloc");
- VerifyAllocCalls();
+ VerifyAllocCalls(false);
}
TEST_F(MallocDebugTest, fill_on_alloc_partial) {
@@ -275,7 +286,7 @@
TEST_F(MallocDebugTest, all_options) {
Init("guard backtrace fill expand_alloc free_track leak_track");
- VerifyAllocCalls();
+ VerifyAllocCalls(true);
}
TEST_F(MallocDebugTest, expand_alloc) {
@@ -624,6 +635,9 @@
ASSERT_STREQ("", getFakeLogBuf().c_str());
std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
+ expected_log += android::base::StringPrintf(
"6 malloc_debug +++ malloc_testing leaked block of size 1024 at %p (leak 1 of 3)\n",
pointer3);
expected_log += "6 malloc_debug Backtrace at time of allocation:\n";
@@ -649,7 +663,6 @@
expected_log += "6 malloc_debug #00 pc 0x1000\n";
expected_log += "6 malloc_debug #01 pc 0x2000\n";
expected_log += "6 malloc_debug #02 pc 0x3000\n";
-
ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
@@ -1022,7 +1035,10 @@
ASSERT_EQ(0U, backtrace_size);
ASSERT_STREQ("", getFakeLogBuf().c_str());
- ASSERT_STREQ("", getFakeLogPrint().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
TEST_F(MallocDebugTest, get_malloc_leak_info_single) {
@@ -1065,7 +1081,10 @@
debug_free(pointer);
ASSERT_STREQ("", getFakeLogBuf().c_str());
- ASSERT_STREQ("", getFakeLogPrint().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
TEST_F(MallocDebugTest, get_malloc_leak_info_multi) {
@@ -1144,7 +1163,10 @@
debug_free(pointers[2]);
ASSERT_STREQ("", getFakeLogBuf().c_str());
- ASSERT_STREQ("", getFakeLogPrint().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
TEST_F(MallocDebugTest, get_malloc_leak_info_multi_skip_empty_backtrace) {
@@ -1215,6 +1237,185 @@
debug_free(pointers[2]);
ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+static std::string SanitizeHeapData(const std::string& data) {
+ // Remove the map data since it's not consistent.
+ std::string sanitized;
+ bool skip_map_data = false;
+ bool map_data_found = false;
+ for (auto& line : android::base::Split(data, "\n")) {
+ if (skip_map_data) {
+ if (line == "END") {
+ if (map_data_found) {
+ sanitized += "MAP_DATA\n";
+ map_data_found = false;
+ }
+ skip_map_data = false;
+ } else {
+ map_data_found = true;
+ continue;
+ }
+ }
+ if (line == "MAPS") {
+ skip_map_data = true;
+ }
+ sanitized += line + '\n';
+ }
+ return sanitized;
+}
+
+void MallocDebugTest::BacktraceDumpOnSignal(bool trigger_with_alloc) {
+ Init("backtrace=4");
+
+ backtrace_fake_add(std::vector<uintptr_t> {0x100, 0x200});
+ backtrace_fake_add(std::vector<uintptr_t> {0x300, 0x400});
+ backtrace_fake_add(std::vector<uintptr_t> {0x500, 0x600});
+
+ backtrace_fake_add(std::vector<uintptr_t> {0xa000, 0xb000});
+ backtrace_fake_add(std::vector<uintptr_t> {0xa100, 0xb200});
+ backtrace_fake_add(std::vector<uintptr_t> {0xa300, 0xb300});
+
+ std::vector<void*> pointers;
+ zygote = 1;
+ pointers.push_back(debug_malloc(100));
+ ASSERT_TRUE(pointers.back() != nullptr);
+ pointers.push_back(debug_malloc(40));
+ ASSERT_TRUE(pointers.back() != nullptr);
+ pointers.push_back(debug_malloc(200));
+ ASSERT_TRUE(pointers.back() != nullptr);
+
+ zygote = 0;
+ pointers.push_back(debug_malloc(10));
+ ASSERT_TRUE(pointers.back() != nullptr);
+ pointers.push_back(debug_malloc(50));
+ ASSERT_TRUE(pointers.back() != nullptr);
+ pointers.push_back(debug_malloc(5));
+ ASSERT_TRUE(pointers.back() != nullptr);
+
+ // Dump all of the data accumulated so far.
+ ASSERT_TRUE(kill(getpid(), SIGRTMAX - 17) == 0);
+ sleep(1);
+
+ // This triggers the dumping.
+ if (trigger_with_alloc) {
+ pointers.push_back(debug_malloc(23));
+ ASSERT_TRUE(pointers.back() != nullptr);
+ } else {
+ debug_free(pointers.back());
+ pointers.pop_back();
+ }
+
+ for (auto* pointer : pointers) {
+ debug_free(pointer);
+ }
+
+ // Read all of the contents.
+ std::string actual;
+ std::string name = android::base::StringPrintf("%s.%d.txt", BACKTRACE_DUMP_PREFIX, getpid());
+ ASSERT_TRUE(android::base::ReadFileToString(name, &actual));
+ ASSERT_EQ(0, unlink(name.c_str()));
+
+ std::string sanitized(SanitizeHeapData(actual));
+
+ std::string expected =
+ "Android Native Heap Dump v1.0\n"
+ "\n"
+ "Total memory: 405\n"
+ "Allocation records: 6\n"
+ "Backtrace size: 4\n"
+ "\n"
+#if defined(__LP64__)
+ "z 0 sz 5 num 1 bt 000000000000a300 000000000000b300\n"
+ "z 0 sz 10 num 1 bt 000000000000a000 000000000000b000\n"
+ "z 0 sz 50 num 1 bt 000000000000a100 000000000000b200\n"
+ "z 1 sz 40 num 1 bt 0000000000000300 0000000000000400\n"
+ "z 1 sz 100 num 1 bt 0000000000000100 0000000000000200\n"
+ "z 1 sz 200 num 1 bt 0000000000000500 0000000000000600\n"
+#else
+ "z 0 sz 5 num 1 bt 0000a300 0000b300\n"
+ "z 0 sz 10 num 1 bt 0000a000 0000b000\n"
+ "z 0 sz 50 num 1 bt 0000a100 0000b200\n"
+ "z 1 sz 40 num 1 bt 00000300 00000400\n"
+ "z 1 sz 100 num 1 bt 00000100 00000200\n"
+ "z 1 sz 200 num 1 bt 00000500 00000600\n"
+#endif
+ "MAPS\n"
+ "MAP_DATA\n"
+ "END\n\n";
+ ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug Dumping to file: /data/local/tmp/backtrace_heap.%d.txt\n\n", getpid());
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, backtrace_dump_on_signal_by_malloc) {
+ BacktraceDumpOnSignal(true);
+}
+
+TEST_F(MallocDebugTest, backtrace_dump_on_signal_by_free) {
+ BacktraceDumpOnSignal(false);
+}
+
+TEST_F(MallocDebugTest, backtrace_dump_on_exit) {
+ pid_t pid;
+ if ((pid = fork()) == 0) {
+ Init("backtrace=4 backtrace_dump_on_exit");
+ backtrace_fake_add(std::vector<uintptr_t> {0x100, 0x200});
+ backtrace_fake_add(std::vector<uintptr_t> {0xa000, 0xb000});
+ backtrace_fake_add(std::vector<uintptr_t> {0xa000, 0xb000, 0xc000});
+
+ std::vector<void*> pointers;
+ pointers.push_back(debug_malloc(300));
+ pointers.push_back(debug_malloc(400));
+ pointers.push_back(debug_malloc(500));
+
+ // Call the exit function manually.
+ debug_finalize();
+ exit(0);
+ }
+ ASSERT_NE(-1, pid);
+ ASSERT_EQ(pid, waitpid(pid, nullptr, 0));
+
+ // Read all of the contents.
+ std::string actual;
+ std::string name = android::base::StringPrintf("%s.%d.exit.txt", BACKTRACE_DUMP_PREFIX, pid);
+ ASSERT_TRUE(android::base::ReadFileToString(name, &actual));
+ ASSERT_EQ(0, unlink(name.c_str()));
+
+ std::string sanitized(SanitizeHeapData(actual));
+
+ std::string expected =
+ "Android Native Heap Dump v1.0\n"
+ "\n"
+ "Total memory: 1200\n"
+ "Allocation records: 3\n"
+ "Backtrace size: 4\n"
+ "\n"
+#if defined(__LP64__)
+ "z 0 sz 300 num 1 bt 0000000000000100 0000000000000200\n"
+ "z 0 sz 400 num 1 bt 000000000000a000 000000000000b000\n"
+ "z 0 sz 500 num 1 bt 000000000000a000 000000000000b000 000000000000c000\n"
+#else
+ "z 0 sz 300 num 1 bt 00000100 00000200\n"
+ "z 0 sz 400 num 1 bt 0000a000 0000b000\n"
+ "z 0 sz 500 num 1 bt 0000a000 0000b000 0000c000\n"
+#endif
+ "MAPS\n"
+ "MAP_DATA\n"
+ "END\n\n";
+ ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
}
@@ -1317,6 +1518,9 @@
std::string expected_log = android::base::StringPrintf(
"4 malloc_debug malloc_testing: Run: 'kill -%d %d' to enable backtracing.\n",
SIGRTMAX - 19, getpid());
+ expected_log += android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
@@ -1439,7 +1643,10 @@
debug_free(pointer);
ASSERT_STREQ("", getFakeLogBuf().c_str());
- ASSERT_STREQ("", getFakeLogPrint().c_str());
+ std::string expected_log = android::base::StringPrintf(
+ "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+ SIGRTMAX - 17, getpid());
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
TEST_F(MallocDebugTest, max_size) {
@@ -1596,6 +1803,7 @@
// Read all of the contents.
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+ ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
ASSERT_STREQ(expected.c_str(), actual.c_str());
@@ -1653,6 +1861,7 @@
// Read all of the contents.
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+ ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
ASSERT_STREQ(expected.c_str(), actual.c_str());
@@ -1694,6 +1903,7 @@
// Read all of the contents.
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+ ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
ASSERT_STREQ(expected.c_str(), actual.c_str());
@@ -1748,6 +1958,7 @@
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
ASSERT_TRUE(android::base::ReadFileToString(RECORD_ALLOCS_FILE, &actual));
+ ASSERT_EQ(0, unlink(RECORD_ALLOCS_FILE));
ASSERT_STREQ(expected.c_str(), actual.c_str());
ASSERT_STREQ("", getFakeLogBuf().c_str());
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index e40f3e3..9aba2e2 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -100,6 +100,7 @@
'__memrchr_chk',
'__pwrite64_chk',
'__pwrite_chk',
+ '__sendto_chk',
'__stack_chk_guard',
'__stpncpy_chk2',
'__strchr_chk',
@@ -184,23 +185,42 @@
# 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).
-in_posix_and_glibc_but_actually_dead = set([
- 'a64l',
- 'confstr',
- 'fattach',
- 'fdetach',
- 'gethostid',
- 'getmsg',
- 'getpmsg',
- 'isastream',
- 'l64a',
- 'putmsg',
- 'putpmsg',
- 'ulimit',
+in_posix_and_glibc_but_dead_or_useless = set([
+ 'a64l', # obsolete
+ 'confstr', # obsolete
+ 'fattach', # obsolete
+ 'fdetach', # obsolete
+ 'gethostid', # obsolete
+ 'getmsg', # obsolete
+ 'getpmsg', # obsolete
+ 'getutxent', # no utmp on Android
+ 'getutxid', # no utmp on Android
+ 'getutxline', # no utmp on Android
+ 'isastream', # obsolete
+ 'l64a', # obsolete
+ 'mq_close', # disallowed by SELinux
+ 'mq_getattr', # disallowed by SELinux
+ 'mq_notify', # disallowed by SELinux
+ 'mq_open', # disallowed by SELinux
+ 'mq_receive', # disallowed by SELinux
+ 'mq_send', # disallowed by SELinux
+ 'mq_setattr', # disallowed by SELinux
+ 'mq_timedreceive', # disallowed by SELinux
+ 'mq_timedsend', # disallowed by SELinux
+ 'mq_unlink', # disallowed by SELinux
+ 'putmsg', # obsolete
+ 'putpmsg', # obsolete
+ 'pututxline', # no utmp on Android
+ 'shm_open', # disallowed by SELinux
+ 'shm_unlink', # disallowed by SELinux
+ 'setutxent', # no utmp on Android
+ 'strfmon', # icu4c
+ 'strfmon_l', # icu4c
+ 'ulimit', # obsolete
])
-posix = posix - in_posix_and_glibc_but_actually_dead
-glibc = glibc - in_posix_and_glibc_but_actually_dead
+posix = posix - in_posix_and_glibc_but_dead_or_useless
+glibc = glibc - in_posix_and_glibc_but_dead_or_useless
if not only_unwanted:
#print 'glibc:'
diff --git a/libc/tools/check-symbols.py b/libc/tools/check-symbols.py
index a6cf50c..6568917 100755
--- a/libc/tools/check-symbols.py
+++ b/libc/tools/check-symbols.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
import glob
import os
diff --git a/libc/tools/generate-NOTICE.py b/libc/tools/generate-NOTICE.py
index d40891c..e59fc7a 100755
--- a/libc/tools/generate-NOTICE.py
+++ b/libc/tools/generate-NOTICE.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# Run with directory arguments from any directory, with no special setup required.
# Or:
# for i in libc libdl libm linker libstdc++ ; do ./libc/tools/generate-NOTICE.py $i > $i/NOTICE ; done
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index e6240a1..46affb7 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# This tool is used to generate the assembler system call stubs,
# the header files listing all available system calls, and the
diff --git a/libc/tools/genversion-scripts.py b/libc/tools/genversion-scripts.py
index 0a98994..5410580 100755
--- a/libc/tools/genversion-scripts.py
+++ b/libc/tools/genversion-scripts.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# This tool is used to generate the version scripts for libc and libm
# for every architecture.
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c b/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c
new file mode 100644
index 0000000..d512857
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/hcreate.c 292767 2015-12-27 07:50:11Z ed $");
+
+#include <search.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+/*
+ * Thread unsafe interface: use a single process-wide hash table and
+ * forward calls to *_r() functions.
+ */
+
+static struct hsearch_data global_hashtable;
+static bool global_hashtable_initialized = false;
+
+int
+hcreate(size_t nel)
+{
+
+ return (1);
+}
+
+void
+hdestroy(void)
+{
+
+ /* Destroy global hash table if present. */
+ if (global_hashtable_initialized) {
+ hdestroy_r(&global_hashtable);
+ global_hashtable_initialized = false;
+ }
+}
+
+ENTRY *
+hsearch(ENTRY item, ACTION action)
+{
+ ENTRY *retval;
+
+ /* Create global hash table if needed. */
+ if (!global_hashtable_initialized) {
+ if (hcreate_r(0, &global_hashtable) == 0)
+ return (NULL);
+ global_hashtable_initialized = true;
+ }
+ if (hsearch_r(item, action, &retval, &global_hashtable) == 0)
+ return (NULL);
+ return (retval);
+}
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hcreate_r.c b/libc/upstream-freebsd/lib/libc/stdlib/hcreate_r.c
new file mode 100644
index 0000000..34db88e
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hcreate_r.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/hcreate_r.c 292767 2015-12-27 07:50:11Z ed $");
+
+#include <search.h>
+#include <stdlib.h>
+
+#include "hsearch.h"
+
+int
+hcreate_r(size_t nel, struct hsearch_data *htab)
+{
+ struct __hsearch *hsearch;
+
+ /*
+ * Allocate a hash table object. Ignore the provided hint and start
+ * off with a table of sixteen entries. In most cases this hint is
+ * just a wild guess. Resizing the table dynamically if the use
+ * increases a threshold does not affect the worst-case running time.
+ */
+ hsearch = malloc(sizeof(*hsearch));
+ if (hsearch == NULL)
+ return 0;
+ hsearch->entries = calloc(16, sizeof(ENTRY));
+ if (hsearch->entries == NULL) {
+ free(hsearch);
+ return 0;
+ }
+
+ /*
+ * Pick a random initialization for the FNV-1a hashing. This makes it
+ * hard to come up with a fixed set of keys to force hash collisions.
+ */
+ arc4random_buf(&hsearch->offset_basis, sizeof(hsearch->offset_basis));
+ hsearch->index_mask = 0xf;
+ hsearch->entries_used = 0;
+ htab->__hsearch = hsearch;
+ return 1;
+}
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hdestroy_r.c b/libc/upstream-freebsd/lib/libc/stdlib/hdestroy_r.c
new file mode 100644
index 0000000..76d8a42
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hdestroy_r.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/hdestroy_r.c 292767 2015-12-27 07:50:11Z ed $");
+
+#include <search.h>
+#include <stdlib.h>
+
+#include "hsearch.h"
+
+void
+hdestroy_r(struct hsearch_data *htab)
+{
+ struct __hsearch *hsearch;
+
+ /* Free hash table object and its entries. */
+ hsearch = htab->__hsearch;
+ free(hsearch->entries);
+ free(hsearch);
+}
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hsearch.h b/libc/upstream-freebsd/lib/libc/stdlib/hsearch.h
new file mode 100644
index 0000000..a0542b5
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hsearch.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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: head/lib/libc/stdlib/hsearch.h 292767 2015-12-27 07:50:11Z ed $
+ */
+
+#ifndef HSEARCH_H
+#define HSEARCH_H
+
+#include <search.h>
+
+struct __hsearch {
+ size_t offset_basis; /* Initial value for FNV-1a hashing. */
+ size_t index_mask; /* Bitmask for indexing the table. */
+ size_t entries_used; /* Number of entries currently used. */
+ ENTRY *entries; /* Hash table entries. */
+};
+
+#endif
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hsearch_r.c b/libc/upstream-freebsd/lib/libc/stdlib/hsearch_r.c
new file mode 100644
index 0000000..9a859d3
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/hsearch_r.c
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/hsearch_r.c 292767 2015-12-27 07:50:11Z ed $");
+
+#include <errno.h>
+#include <limits.h>
+#include <search.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "hsearch.h"
+
+/*
+ * Look up an unused entry in the hash table for a given hash. For this
+ * implementation we use quadratic probing. Quadratic probing has the
+ * advantage of preventing primary clustering.
+ */
+static ENTRY *
+hsearch_lookup_free(struct __hsearch *hsearch, size_t hash)
+{
+ size_t index, i;
+
+ for (index = hash, i = 0;; index += ++i) {
+ ENTRY *entry = &hsearch->entries[index & hsearch->index_mask];
+ if (entry->key == NULL)
+ return (entry);
+ }
+}
+
+/*
+ * Computes an FNV-1a hash of the key. Depending on the pointer size, this
+ * either uses the 32- or 64-bit FNV prime.
+ */
+static size_t
+hsearch_hash(size_t offset_basis, const char *str)
+{
+ size_t hash;
+
+ hash = offset_basis;
+ while (*str != '\0') {
+ hash ^= (uint8_t)*str++;
+ if (sizeof(size_t) * CHAR_BIT <= 32)
+ hash *= UINT32_C(16777619);
+ else
+ hash *= UINT64_C(1099511628211);
+ }
+ return (hash);
+}
+
+int
+hsearch_r(ENTRY item, ACTION action, ENTRY **retval, struct hsearch_data *htab)
+{
+ struct __hsearch *hsearch;
+ ENTRY *entry, *old_entries, *new_entries;
+ size_t hash, index, i, old_hash, old_count, new_count;
+
+ hsearch = htab->__hsearch;
+ hash = hsearch_hash(hsearch->offset_basis, item.key);
+
+ /*
+ * Search the hash table for an existing entry for this key.
+ * Stop searching if we run into an unused hash table entry.
+ */
+ for (index = hash, i = 0;; index += ++i) {
+ entry = &hsearch->entries[index & hsearch->index_mask];
+ if (entry->key == NULL)
+ break;
+ if (strcmp(entry->key, item.key) == 0) {
+ *retval = entry;
+ return (1);
+ }
+ }
+
+ /* Only perform the insertion if action is set to ENTER. */
+ if (action == FIND) {
+ errno = ESRCH;
+ return (0);
+ }
+
+ if (hsearch->entries_used * 2 >= hsearch->index_mask) {
+ /* Preserve the old hash table entries. */
+ old_count = hsearch->index_mask + 1;
+ old_entries = hsearch->entries;
+
+ /*
+ * Allocate and install a new table if insertion would
+ * yield a hash table that is more than 50% used. By
+ * using 50% as a threshold, a lookup will only take up
+ * to two steps on average.
+ */
+ new_count = (hsearch->index_mask + 1) * 2;
+ new_entries = calloc(new_count, sizeof(ENTRY));
+ if (new_entries == NULL)
+ return (0);
+ hsearch->entries = new_entries;
+ hsearch->index_mask = new_count - 1;
+
+ /* Copy over the entries from the old table to the new table. */
+ for (i = 0; i < old_count; ++i) {
+ entry = &old_entries[i];
+ if (entry->key != NULL) {
+ old_hash = hsearch_hash(hsearch->offset_basis,
+ entry->key);
+ *hsearch_lookup_free(hsearch, old_hash) =
+ *entry;
+ }
+ }
+
+ /* Destroy the old hash table entries. */
+ free(old_entries);
+
+ /*
+ * Perform a new lookup for a free table entry, so that
+ * we insert the entry into the new hash table.
+ */
+ hsearch = htab->__hsearch;
+ entry = hsearch_lookup_free(hsearch, hash);
+ }
+
+ /* Insert the new entry into the hash table. */
+ *entry = item;
+ ++hsearch->entries_used;
+ *retval = entry;
+ return (1);
+}
diff --git a/libc/upstream-openbsd/android/include/arc4random.h b/libc/upstream-openbsd/android/include/arc4random.h
index d006045..4c4be0e 100644
--- a/libc/upstream-openbsd/android/include/arc4random.h
+++ b/libc/upstream-openbsd/android/include/arc4random.h
@@ -45,10 +45,8 @@
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
#endif
-static inline void
-_getentropy_fail(void)
-{
- async_safe_fatal("getentropy failed");
+static inline void _getentropy_fail(void) {
+ async_safe_fatal("getentropy failed: %s", strerror(errno));
}
volatile sig_atomic_t _rs_forked;
diff --git a/libdl/Android.bp b/libdl/Android.bp
index ffdf7f7..9f67ee8 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -44,7 +44,12 @@
version_script: "libdl.x86_64.map",
},
},
- srcs: ["libdl.c", "libdl_cfi.cpp"],
+ shared: {
+ srcs: ["libdl.c", "libdl_cfi.cpp"],
+ },
+ static: {
+ srcs: [ "libdl_static.c" ],
+ },
cflags: [
"-Wall",
"-Wextra",
diff --git a/libdl/libdl_cfi.cpp b/libdl/libdl_cfi.cpp
index 483364f..1dd5b21 100644
--- a/libdl/libdl_cfi.cpp
+++ b/libdl/libdl_cfi.cpp
@@ -52,7 +52,10 @@
static uintptr_t cfi_check_addr(uint16_t v, void* Ptr) {
uintptr_t addr = reinterpret_cast<uintptr_t>(Ptr);
- uintptr_t aligned_addr = align_up(addr, CFIShadow::kShadowAlign);
+ // The aligned range of [0, kShadowAlign) uses a single shadow element, therefore all pointers in
+ // this range must get the same aligned_addr below. This matches CFIShadowWriter::Add; not the
+ // same as align_up().
+ uintptr_t aligned_addr = align_down(addr, CFIShadow::kShadowAlign) + CFIShadow::kShadowAlign;
uintptr_t p = aligned_addr - (static_cast<uintptr_t>(v - CFIShadow::kRegularShadowMin)
<< CFIShadow::kCfiCheckGranularity);
#ifdef __arm__
diff --git a/libdl/libdl_static.c b/libdl/libdl_static.c
new file mode 100644
index 0000000..0dbd73f
--- /dev/null
+++ b/libdl/libdl_static.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#include <dlfcn.h>
+#include <link.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+// Proxy calls to bionic loader
+void* dlopen(const char* filename __unused, int flag __unused) {
+ return NULL;
+}
+
+char* dlerror() {
+ return NULL;
+}
+
+void* dlsym(void* handle __unused, const char* symbol __unused) {
+ return NULL;
+}
+
+void* dlvsym(void* handle __unused,
+ const char* symbol __unused,
+ const char* version __unused) {
+ return NULL;
+}
+
+int dladdr(const void* addr __unused, Dl_info* info __unused) {
+ return 0;
+}
+
+int dlclose(void* handle __unused) {
+ return -1;
+}
+
+#if defined(__arm__)
+_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc __unused, int* pcount __unused) {
+ return 0;
+}
+#endif
+
+void android_set_application_target_sdk_version(uint32_t target __unused) {
+}
+
diff --git a/libm/Android.bp b/libm/Android.bp
index 75e8957..bf86264 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -283,7 +283,7 @@
srcs: [
"arm/fenv.c",
],
- armv7_a_neon: {
+ neon: {
srcs: [
"arm/sqrt.S",
"arm/floor.S",
@@ -506,6 +506,7 @@
],
cflags: [
+ "-D__BIONIC_LP32_USE_LONG_DOUBLE",
"-D__BIONIC_NO_MATH_INLINES",
"-D_BSD_SOURCE",
"-DFLT_EVAL_METHOD=0",
diff --git a/libm/libm.map.txt b/libm/libm.map.txt
index 1fb16b7..1f9a3f9 100644
--- a/libm/libm.map.txt
+++ b/libm/libm.map.txt
@@ -271,7 +271,7 @@
*;
};
-LIBC_O {
+LIBC_O { # introduced=O
global:
cacoshl;
cacosl;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 59e4bac..a843b7b 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -286,8 +286,7 @@
struct stat* file_stat, off64_t file_offset,
uint32_t rtld_flags) {
if (strlen(name) >= PATH_MAX) {
- DL_ERR("library name \"%s\" too long", name);
- return nullptr;
+ async_safe_fatal("library name \"%s\" too long", name);
}
TRACE("name %s: allocating soinfo for ns=%p", name, ns);
@@ -3211,8 +3210,23 @@
default:
if (!relocating_linker) {
- DL_WARN("\"%s\" unused DT entry: type %p arg %p", get_realpath(),
- reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
+ const char* tag_name;
+ if (d->d_tag == DT_RPATH) {
+ tag_name = "DT_RPATH";
+ } else if (d->d_tag == DT_ENCODING) {
+ tag_name = "DT_ENCODING";
+ } else if (d->d_tag >= DT_LOOS && d->d_tag <= DT_HIOS) {
+ tag_name = "unknown OS-specific";
+ } else if (d->d_tag >= DT_LOPROC && d->d_tag <= DT_HIPROC) {
+ tag_name = "unknown processor-specific";
+ } else {
+ tag_name = "unknown";
+ }
+ DL_WARN("\"%s\" unused DT entry: %s (type %p arg %p)",
+ get_realpath(),
+ tag_name,
+ reinterpret_cast<void*>(d->d_tag),
+ reinterpret_cast<void*>(d->d_un.d_val));
}
break;
}
diff --git a/linker/linker_allocator.cpp b/linker/linker_allocator.cpp
index fd6f496..a37e910 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -200,12 +200,10 @@
}
void LinkerSmallObjectAllocator::alloc_page() {
- static_assert(sizeof(page_info) % 16 == 0,
- "sizeof(page_info) is not multiple of 16");
- void* map_ptr = mmap(nullptr, PAGE_SIZE,
- PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+ static_assert(sizeof(page_info) % 16 == 0, "sizeof(page_info) is not multiple of 16");
+ void* map_ptr = mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (map_ptr == MAP_FAILED) {
- async_safe_fatal("mmap failed");
+ async_safe_fatal("mmap failed: %s", strerror(errno));
}
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE, "linker_alloc_small_objects");
@@ -246,11 +244,11 @@
void* LinkerMemoryAllocator::alloc_mmap(size_t size) {
size_t allocated_size = PAGE_END(size + sizeof(page_info));
- void* map_ptr = mmap(nullptr, allocated_size,
- PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+ void* map_ptr = mmap(nullptr, allocated_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
+ -1, 0);
if (map_ptr == MAP_FAILED) {
- async_safe_fatal("mmap failed");
+ async_safe_fatal("mmap failed: %s", strerror(errno));
}
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "linker_alloc_lob");
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index 80ae508..9c16828 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -88,12 +88,12 @@
T* allocate(size_t n, const T* hint = nullptr) {
size_t size = n * sizeof(T);
- void* ptr = mmap(const_cast<T*>(hint), size,
- PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+ void* ptr = mmap(const_cast<T*>(hint), size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
+ -1, 0);
if (ptr == MAP_FAILED) {
// Spec says we need to throw std::bad_alloc here but because our
// code does not support exception handling anyways - we are going to abort.
- async_safe_fatal("mmap failed");
+ async_safe_fatal("mmap failed: %s", strerror(errno));
}
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "linker_alloc_vector");
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index 605e185..abb1ebd 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -117,7 +117,7 @@
"Invalid sizeof(LinkerBlockAllocatorPage)");
LinkerBlockAllocatorPage* page = reinterpret_cast<LinkerBlockAllocatorPage*>(
- mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0));
+ mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0));
if (page == MAP_FAILED) {
abort(); // oom
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index e8b02d6..3862d8c 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -276,11 +276,8 @@
const char* executable_path = get_executable_path();
soinfo* si = soinfo_alloc(&g_default_namespace, executable_path, &file_stat, 0, RTLD_GLOBAL);
- if (si == nullptr) {
- async_safe_fatal("Couldn't allocate soinfo: out of memory?");
- }
- /* bootstrap the link map, the main exe always needs to be first */
+ // Bootstrap the link map, the main exe always needs to be first.
si->set_main_executable();
link_map* map = &(si->link_map_head);
diff --git a/tests/Android.bp b/tests/Android.bp
index b5f8dc8..3731156 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -57,6 +57,7 @@
"buffer_tests.cpp",
"bug_26110743_test.cpp",
"complex_test.cpp",
+ "complex_force_long_double_test.cpp",
"ctype_test.cpp",
"dirent_test.cpp",
"elf_test.cpp",
@@ -66,6 +67,7 @@
"eventfd_test.cpp",
"fcntl_test.cpp",
"fenv_test.cpp",
+ "float_test.cpp",
"ftw_test.cpp",
"getauxval_test.cpp",
"getcwd_test.cpp",
@@ -73,14 +75,17 @@
"iconv_test.cpp",
"ifaddrs_test.cpp",
"inttypes_test.cpp",
+ "iso646_test.c",
"langinfo_test.cpp",
"leak_test.cpp",
"libgen_basename_test.cpp",
"libgen_test.cpp",
+ "limits_test.cpp",
"linux_swab_test.cpp",
"locale_test.cpp",
"malloc_test.cpp",
"math_test.cpp",
+ "math_force_long_double_test.cpp",
"mntent_test.cpp",
"netdb_test.cpp",
"net_if_test.cpp",
@@ -102,12 +107,16 @@
"stack_protector_test.cpp",
"stack_protector_test_helper.cpp",
"stack_unwinding_test.cpp",
+ "stdalign_test.cpp",
+ "stdarg_test.cpp",
"stdatomic_test.cpp",
+ "stdbool_test.c",
"stdint_test.cpp",
"stdio_nofortify_test.cpp",
"stdio_test.cpp",
"stdio_ext_test.cpp",
"stdlib_test.cpp",
+ "stdnoreturn_test.cpp",
"string_nofortify_test.cpp",
"string_test.cpp",
"string_posix_strerror_r_test.cpp",
@@ -142,6 +151,7 @@
"sys_xattr_test.cpp",
"system_properties_test.cpp",
"system_properties_test2.cpp",
+ "tgmath_test.c",
"time_test.cpp",
"uchar_test.cpp",
"unistd_nofortify_test.cpp",
@@ -210,13 +220,11 @@
// Ignore that we don't have ASAN symbols linked in.
allow_undefined_symbols: true,
srcs: ["fortify_compilation_test.cpp"],
- clang: true,
}
cc_test_library {
name: "libfortify1-tests-clang",
defaults: ["bionic_fortify_tests_defaults", "bionic_tests_defaults"],
- clang: true,
cflags: [
"-D_FORTIFY_SOURCE=1",
"-DTEST_NAME=Fortify1_clang"
@@ -229,7 +237,6 @@
cc_test_library {
name: "libfortify2-tests-clang",
defaults: ["bionic_fortify_tests_defaults", "bionic_tests_defaults"],
- clang: true,
cflags: [
"-D_FORTIFY_SOURCE=2",
"-DTEST_NAME=Fortify2_clang"
@@ -418,7 +425,6 @@
cc_test {
name: "bionic-unit-tests",
defaults: ["bionic_unit_tests_defaults", "bionic_tests_defaults"],
- clang: true,
target: {
android: {
diff --git a/tests/complex_force_long_double_test.cpp b/tests/complex_force_long_double_test.cpp
new file mode 100644
index 0000000..2ea7bd4
--- /dev/null
+++ b/tests/complex_force_long_double_test.cpp
@@ -0,0 +1,2 @@
+#define __BIONIC_LP32_USE_LONG_DOUBLE
+#include "complex_test.cpp"
diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp
index 3a5ef74..85b20de 100644
--- a/tests/complex_test.cpp
+++ b/tests/complex_test.cpp
@@ -16,6 +16,12 @@
#include <gtest/gtest.h>
+#if defined(__BIONIC_LP32_USE_LONG_DOUBLE)
+#define COMPLEX_TEST complex_h_force_long_double
+#else
+#define COMPLEX_TEST complex_h
+#endif
+
// This file is compiled against both glibc and bionic, and our complex.h
// depends on bionic-specific macros, so hack around that.
#include <sys/cdefs.h>
@@ -24,6 +30,7 @@
#define __INTRODUCED_IN_32(x)
#define __INTRODUCED_IN_64(x)
#define __INTRODUCED_IN_FUTURE
+#define __RENAME_LDBL(a,b,c)
#endif
// libc++ actively gets in the way of including <complex.h> from C++, so we
@@ -36,6 +43,7 @@
#include <math.h> // For M_PI_2/M_PI_2l.
+#if 0
// Note that gtest doesn't support complex numbers, so the output from
// assertion failures is misleading/useless (at best you'll only see the real
// part).
@@ -54,267 +62,268 @@
os << "(" << creall(c) << "," << cimagl(c) << "i)";
return os;
}
+#endif
-TEST(complex, cabs) {
+TEST(COMPLEX_TEST, cabs) {
ASSERT_EQ(0.0, cabs(0));
}
-TEST(complex, cabsf) {
+TEST(COMPLEX_TEST, cabsf) {
ASSERT_EQ(0.0, cabsf(0));
}
-TEST(complex, cabsl) {
+TEST(COMPLEX_TEST, cabsl) {
ASSERT_EQ(0.0, cabsl(0));
}
-TEST(complex, cacos) {
+TEST(COMPLEX_TEST, cacos) {
ASSERT_EQ(M_PI_2, cacos(0.0));
}
-TEST(complex, cacosf) {
+TEST(COMPLEX_TEST, cacosf) {
ASSERT_EQ(static_cast<float>(M_PI_2), cacosf(0.0));
}
-TEST(complex, cacosl) {
+TEST(COMPLEX_TEST, cacosl) {
ASSERT_EQ(M_PI_2l, cacosl(0.0));
}
-TEST(complex, cacosh) {
+TEST(COMPLEX_TEST, cacosh) {
ASSERT_EQ(0.0, cacosh(1.0));
}
-TEST(complex, cacoshl) {
+TEST(COMPLEX_TEST, cacoshl) {
ASSERT_EQ(0.0, cacoshl(1.0));
}
-TEST(complex, cacoshf) {
+TEST(COMPLEX_TEST, cacoshf) {
ASSERT_EQ(0.0, cacoshf(1.0));
}
-TEST(complex, carg) {
+TEST(COMPLEX_TEST, carg) {
ASSERT_EQ(0.0, carg(0));
}
-TEST(complex, cargf) {
+TEST(COMPLEX_TEST, cargf) {
ASSERT_EQ(0.0, cargf(0));
}
-TEST(complex, cargl) {
+TEST(COMPLEX_TEST, cargl) {
ASSERT_EQ(0.0, cargl(0));
}
-TEST(complex, casin) {
+TEST(COMPLEX_TEST, casin) {
ASSERT_EQ(0.0, casin(0));
}
-TEST(complex, casinf) {
+TEST(COMPLEX_TEST, casinf) {
ASSERT_EQ(0.0, casinf(0));
}
-TEST(complex, casinl) {
+TEST(COMPLEX_TEST, casinl) {
ASSERT_EQ(0.0, casinl(0));
}
-TEST(complex, casinh) {
+TEST(COMPLEX_TEST, casinh) {
ASSERT_EQ(0.0, casinh(0));
}
-TEST(complex, casinhf) {
+TEST(COMPLEX_TEST, casinhf) {
ASSERT_EQ(0.0, casinhf(0));
}
-TEST(complex, casinhl) {
+TEST(COMPLEX_TEST, casinhl) {
ASSERT_EQ(0.0, casinhl(0));
}
-TEST(complex, catan) {
+TEST(COMPLEX_TEST, catan) {
ASSERT_EQ(0.0, catan(0));
}
-TEST(complex, catanf) {
+TEST(COMPLEX_TEST, catanf) {
ASSERT_EQ(0.0, catanf(0));
}
-TEST(complex, catanl) {
+TEST(COMPLEX_TEST, catanl) {
ASSERT_EQ(0.0, catanl(0));
}
-TEST(complex, catanh) {
+TEST(COMPLEX_TEST, catanh) {
ASSERT_EQ(0.0, catanh(0));
}
-TEST(complex, catanhf) {
+TEST(COMPLEX_TEST, catanhf) {
ASSERT_EQ(0.0, catanhf(0));
}
-TEST(complex, catanhl) {
+TEST(COMPLEX_TEST, catanhl) {
ASSERT_EQ(0.0, catanhl(0));
}
-TEST(complex, ccos) {
+TEST(COMPLEX_TEST, ccos) {
ASSERT_EQ(1.0, ccos(0));
}
-TEST(complex, ccosf) {
+TEST(COMPLEX_TEST, ccosf) {
ASSERT_EQ(1.0, ccosf(0));
}
-TEST(complex, ccosl) {
+TEST(COMPLEX_TEST, ccosl) {
ASSERT_EQ(1.0, ccosl(0));
}
-TEST(complex, ccosh) {
+TEST(COMPLEX_TEST, ccosh) {
ASSERT_EQ(1.0, ccosh(0));
}
-TEST(complex, ccoshf) {
+TEST(COMPLEX_TEST, ccoshf) {
ASSERT_EQ(1.0, ccoshf(0));
}
-TEST(complex, ccoshl) {
+TEST(COMPLEX_TEST, ccoshl) {
ASSERT_EQ(1.0, ccoshl(0));
}
-TEST(complex, cexp) {
+TEST(COMPLEX_TEST, cexp) {
ASSERT_EQ(1.0, cexp(0));
}
-TEST(complex, cexpf) {
+TEST(COMPLEX_TEST, cexpf) {
ASSERT_EQ(1.0, cexpf(0));
}
-TEST(complex, cexpl) {
+TEST(COMPLEX_TEST, cexpl) {
ASSERT_EQ(1.0, cexpl(0));
}
-TEST(complex, cimag) {
+TEST(COMPLEX_TEST, cimag) {
ASSERT_EQ(0.0, cimag(0));
}
-TEST(complex, cimagf) {
+TEST(COMPLEX_TEST, cimagf) {
ASSERT_EQ(0.0f, cimagf(0));
}
-TEST(complex, cimagl) {
+TEST(COMPLEX_TEST, cimagl) {
ASSERT_EQ(0.0, cimagl(0));
}
-TEST(complex, clog) {
+TEST(COMPLEX_TEST, clog) {
ASSERT_EQ(0.0, clog(1.0));
}
-TEST(complex, clogf) {
+TEST(COMPLEX_TEST, clogf) {
ASSERT_EQ(0.0f, clogf(1.0f));
}
-TEST(complex, clogl) {
+TEST(COMPLEX_TEST, clogl) {
ASSERT_EQ(0.0L, clogl(1.0L));
}
-TEST(complex, conj) {
+TEST(COMPLEX_TEST, conj) {
ASSERT_EQ(0.0, conj(0));
}
-TEST(complex, conjf) {
+TEST(COMPLEX_TEST, conjf) {
ASSERT_EQ(0.0f, conjf(0));
}
-TEST(complex, conjl) {
+TEST(COMPLEX_TEST, conjl) {
ASSERT_EQ(0.0, conjl(0));
}
-TEST(complex, cpow) {
+TEST(COMPLEX_TEST, cpow) {
ASSERT_EQ(8.0, cpow(2.0, 3.0));
}
-TEST(complex, cpowf) {
+TEST(COMPLEX_TEST, cpowf) {
ASSERT_EQ(8.0f, cpowf(2.0f, 3.0f));
}
-TEST(complex, cpowl) {
+TEST(COMPLEX_TEST, cpowl) {
ASSERT_EQ(8.0L, cpowl(2.0L, 3.0L));
}
-TEST(complex, cproj) {
+TEST(COMPLEX_TEST, cproj) {
ASSERT_EQ(0.0, cproj(0));
}
-TEST(complex, cprojf) {
+TEST(COMPLEX_TEST, cprojf) {
ASSERT_EQ(0.0f, cprojf(0));
}
-TEST(complex, cprojl) {
+TEST(COMPLEX_TEST, cprojl) {
ASSERT_EQ(0.0, cprojl(0));
}
-TEST(complex, creal) {
+TEST(COMPLEX_TEST, creal) {
ASSERT_EQ(2.0, creal(2.0 + 3.0I));
}
-TEST(complex, crealf) {
+TEST(COMPLEX_TEST, crealf) {
ASSERT_EQ(2.0f, crealf(2.0f + 3.0fI));
}
-TEST(complex, creall) {
+TEST(COMPLEX_TEST, creall) {
ASSERT_EQ(2.0, creall(2.0L + 3.0LI));
}
-TEST(complex, csin) {
+TEST(COMPLEX_TEST, csin) {
ASSERT_EQ(0.0, csin(0));
}
-TEST(complex, csinf) {
+TEST(COMPLEX_TEST, csinf) {
ASSERT_EQ(0.0, csinf(0));
}
-TEST(complex, csinl) {
+TEST(COMPLEX_TEST, csinl) {
ASSERT_EQ(0.0, csinl(0));
}
-TEST(complex, csinh) {
+TEST(COMPLEX_TEST, csinh) {
ASSERT_EQ(0.0, csinh(0));
}
-TEST(complex, csinhf) {
+TEST(COMPLEX_TEST, csinhf) {
ASSERT_EQ(0.0, csinhf(0));
}
-TEST(complex, csinhl) {
+TEST(COMPLEX_TEST, csinhl) {
ASSERT_EQ(0.0, csinhl(0));
}
-TEST(complex, csqrt) {
+TEST(COMPLEX_TEST, csqrt) {
ASSERT_EQ(0.0, csqrt(0));
}
-TEST(complex, csqrtf) {
+TEST(COMPLEX_TEST, csqrtf) {
ASSERT_EQ(0.0f, csqrtf(0));
}
-TEST(complex, csqrtl) {
+TEST(COMPLEX_TEST, csqrtl) {
ASSERT_EQ(0.0, csqrtl(0));
}
-TEST(complex, ctan) {
+TEST(COMPLEX_TEST, ctan) {
ASSERT_EQ(0.0, ctan(0));
}
-TEST(complex, ctanf) {
+TEST(COMPLEX_TEST, ctanf) {
ASSERT_EQ(0.0, ctanf(0));
}
-TEST(complex, ctanl) {
+TEST(COMPLEX_TEST, ctanl) {
ASSERT_EQ(0.0, ctanl(0));
}
-TEST(complex, ctanh) {
+TEST(COMPLEX_TEST, ctanh) {
ASSERT_EQ(0.0, ctanh(0));
}
-TEST(complex, ctanhf) {
+TEST(COMPLEX_TEST, ctanhf) {
ASSERT_EQ(0.0, ctanhf(0));
}
-TEST(complex, ctanhl) {
+TEST(COMPLEX_TEST, ctanhl) {
ASSERT_EQ(0.0, ctanhl(0));
}
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 857640a..aaf2c37 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -16,6 +16,10 @@
#include <gtest/gtest.h>
+#if defined(__BIONIC__)
+#include <android-base/properties.h>
+#endif
+
#include <dlfcn.h>
#include <libgen.h>
#include <limits.h>
@@ -226,6 +230,12 @@
// This test is only for CTS.
return;
}
+ std::string build_type = android::base::GetProperty("ro.build.type", "user");
+ if (build_type == "userdebug" || build_type == "eng") {
+ // Skip the test for non production devices
+ return;
+ }
+
std::string error_message = "CANNOT LINK EXECUTABLE \"" + get_testlib_root() + "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" not found\n";
std::string helper = get_testlib_root() +
"/ld_config_test_helper/ld_config_test_helper";
diff --git a/tests/float_test.cpp b/tests/float_test.cpp
new file mode 100644
index 0000000..a75214e
--- /dev/null
+++ b/tests/float_test.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <float.h>
+
+TEST(float_h, macros) {
+#if !defined(FLT_RADIX)
+#error FLT_RADIX
+#endif
+#if !defined(DECIMAL_DIG)
+#error DECIMAL_DIG
+#endif
+#if !defined(FLT_DECIMAL_DIG)
+#error FLT_DECIMAL_DIG
+#endif
+#if !defined(DBL_DECIMAL_DIG)
+#error DBL_DECIMAL_DIG
+#endif
+#if !defined(LDBL_DECIMAL_DIG)
+#error LDBL_DECIMAL_DIG
+#endif
+#if !defined(FLT_MIN)
+#error FLT_MIN
+#endif
+#if !defined(DBL_MIN)
+#error DBL_MIN
+#endif
+#if !defined(LDBL_MIN)
+#error LDBL_MIN
+#endif
+#if !defined(FLT_EPSILON)
+#error FLT_EPSILON
+#endif
+#if !defined(DBL_EPSILON)
+#error DBL_EPSILON
+#endif
+#if !defined(LDBL_EPSILON)
+#error LDBL_EPSILON
+#endif
+#if !defined(FLT_DIG)
+#error FLT_DIG
+#endif
+#if !defined(DBL_DIG)
+#error DBL_DIG
+#endif
+#if !defined(LDBL_DIG)
+#error LDBL_DIG
+#endif
+#if !defined(FLT_MANT_DIG)
+#error FLT_MANT_DIG
+#endif
+#if !defined(DBL_MANT_DIG)
+#error DBL_MANT_DIG
+#endif
+#if !defined(LDBL_MANT_DIG)
+#error LDBL_MANT_DIG
+#endif
+#if !defined(FLT_MIN_EXP)
+#error FLT_MIN_EXP
+#endif
+#if !defined(DBL_MIN_EXP)
+#error DBL_MIN_EXP
+#endif
+#if !defined(LDBL_MIN_EXP)
+#error LDBL_MIN_EXP
+#endif
+#if !defined(FLT_MIN_10_EXP)
+#error FLT_MIN_10_EXP
+#endif
+#if !defined(DBL_MIN_10_EXP)
+#error DBL_MIN_10_EXP
+#endif
+#if !defined(LDBL_MIN_10_EXP)
+#error LDBL_MIN_10_EXP
+#endif
+#if !defined(FLT_MAX_EXP)
+#error FLT_MAX_EXP
+#endif
+#if !defined(DBL_MAX_EXP)
+#error DBL_MAX_EXP
+#endif
+#if !defined(LDBL_MAX_EXP)
+#error LDBL_MAX_EXP
+#endif
+#if !defined(FLT_MAX_10_EXP)
+#error FLT_MAX_10_EXP
+#endif
+#if !defined(DBL_MAX_10_EXP)
+#error DBL_MAX_10_EXP
+#endif
+#if !defined(LDBL_MAX_10_EXP)
+#error LDBL_MAX_10_EXP
+#endif
+#if !defined(FLT_ROUNDS)
+#error FLT_ROUNDS
+#endif
+#if !defined(FLT_EVAL_METHOD)
+#error FLT_EVAL_METHOD
+#endif
+// TODO: FLT_HAS_SUBNORM currently missing from clang. Negate this test when fixed.
+#if defined(FLT_HAS_SUBNORM)
+#error FLT_HAS_SUBNORM
+#endif
+// TODO: DBL_HAS_SUBNORM currently missing from clang. Negate this test when fixed.
+#if defined(DBL_HAS_SUBNORM)
+#error DBL_HAS_SUBNORM
+#endif
+// TODO: LDBL_HAS_SUBNORM currently missing from clang. Negate this test when fixed.
+#if defined(LDBL_HAS_SUBNORM)
+#error LDBL_HAS_SUBNORM
+#endif
+}
diff --git a/tests/iconv_test.cpp b/tests/iconv_test.cpp
index b197152..768b4fd 100644
--- a/tests/iconv_test.cpp
+++ b/tests/iconv_test.cpp
@@ -427,3 +427,29 @@
TEST(iconv, iconv_EINVAL_utf32le_short) {
Check(EINVAL, "utf32le", "\x24\x00\x00", 3); // Missing final byte.
}
+
+TEST(iconv, iconv_initial_shift_state) {
+ // POSIX: "For state-dependent encodings, the conversion descriptor
+ // cd is placed into its initial shift state by a call for which inbuf
+ // is a null pointer, or for which inbuf points to a null pointer."
+ iconv_t c = iconv_open("utf8", "utf8");
+ char* in = nullptr;
+ size_t in_bytes = 0;
+ wchar_t out_buf[16];
+ size_t out_bytes = sizeof(out_buf);
+ char* out = reinterpret_cast<char*>(out_buf);
+
+ // Points to a null pointer...
+ errno = 0;
+ ASSERT_EQ(static_cast<size_t>(0), iconv(c, &in, &in_bytes, &out, &out_bytes));
+ EXPECT_EQ(0, errno);
+ EXPECT_EQ(sizeof(out_buf), out_bytes);
+
+ // Is a null pointer...
+ errno = 0;
+ ASSERT_EQ(static_cast<size_t>(0), iconv(c, nullptr, &in_bytes, &out, &out_bytes));
+ EXPECT_EQ(0, errno);
+ EXPECT_EQ(sizeof(out_buf), out_bytes);
+
+ EXPECT_EQ(0, iconv_close(c));
+}
diff --git a/tests/inttypes_test.cpp b/tests/inttypes_test.cpp
index 01d6b82..da12ec4 100644
--- a/tests/inttypes_test.cpp
+++ b/tests/inttypes_test.cpp
@@ -156,3 +156,32 @@
wcstoumax(L"123", NULL, 37);
ASSERT_EQ(EINVAL, errno);
}
+
+TEST(inttypes, div) {
+ div_t r = div(-5, 3);
+ ASSERT_EQ(-1, r.quot);
+ ASSERT_EQ(-2, r.rem);
+}
+
+TEST(inttypes, ldiv) {
+ ldiv_t r = ldiv(-5, 3);
+ ASSERT_EQ(-1, r.quot);
+ ASSERT_EQ(-2, r.rem);
+}
+
+TEST(inttypes, lldiv) {
+ lldiv_t r = lldiv(-5, 3);
+ ASSERT_EQ(-1, r.quot);
+ ASSERT_EQ(-2, r.rem);
+}
+
+TEST(inttypes, imaxdiv) {
+ imaxdiv_t r = imaxdiv(-5, 3);
+ ASSERT_EQ(-1, r.quot);
+ ASSERT_EQ(-2, r.rem);
+}
+
+TEST(inttypes, imaxabs) {
+ ASSERT_EQ(INTMAX_MAX, imaxabs(-INTMAX_MAX));
+ ASSERT_EQ(INTMAX_MAX, imaxabs(INTMAX_MAX));
+}
diff --git a/tests/iso646_test.c b/tests/iso646_test.c
new file mode 100644
index 0000000..618f027
--- /dev/null
+++ b/tests/iso646_test.c
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#include <iso646.h>
+
+#if !defined(and)
+#error and
+#endif
+#if !defined(and_eq)
+#error and_eq
+#endif
+#if !defined(bitand)
+#error bitand
+#endif
+#if !defined(bitor)
+#error bitor
+#endif
+#if !defined(compl)
+#error compl
+#endif
+#if !defined(not)
+#error not
+#endif
+#if !defined(not_eq)
+#error not_eq
+#endif
+#if !defined(or)
+#error or
+#endif
+#if !defined(or_eq)
+#error or_eq
+#endif
+#if !defined(xor)
+#error xor
+#endif
+#if !defined(xor_eq)
+#error xor_eq
+#endif
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
new file mode 100644
index 0000000..1d48ffe
--- /dev/null
+++ b/tests/limits_test.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <limits.h>
+
+TEST(limits, macros) {
+#if CHAR_BIT != 8
+#error Insane CHAR_BIT
+#endif
+#if !defined(MB_LEN_MAX)
+#error MB_LEN_MAX
+#endif
+#if !defined(CHAR_MIN)
+#error CHAR_MIN
+#endif
+#if !defined(CHAR_MAX)
+#error CHAR_MAX
+#endif
+#if !defined(SCHAR_MIN)
+#error SCHAR_MIN
+#endif
+#if !defined(SCHAR_MAX)
+#error SCHAR_MAX
+#endif
+#if !defined(SHRT_MIN)
+#error SHRT_MIN
+#endif
+#if !defined(SHRT_MAX)
+#error SHRT_MAX
+#endif
+#if !defined(INT_MIN)
+#error INT_MIN
+#endif
+#if !defined(INT_MAX)
+#error INT_MAX
+#endif
+#if !defined(LONG_MIN)
+#error LONG_MIN
+#endif
+#if !defined(LONG_MAX)
+#error LONG_MAX
+#endif
+#if !defined(LLONG_MIN)
+#error LLONG_MIN
+#endif
+#if !defined(LLONG_MAX)
+#error LLONG_MAX
+#endif
+#if !defined(UCHAR_MAX)
+#error UCHAR_MAX
+#endif
+#if !defined(USHRT_MAX)
+#error USHRT_MAX
+#endif
+#if !defined(UINT_MAX)
+#error UINT_MAX
+#endif
+#if !defined(ULONG_MAX)
+#error ULONG_MAX
+#endif
+#if !defined(ULLONG_MAX)
+#error ULLONG_MAX
+#endif
+}
diff --git a/tests/math_force_long_double_test.cpp b/tests/math_force_long_double_test.cpp
new file mode 100644
index 0000000..432182b
--- /dev/null
+++ b/tests/math_force_long_double_test.cpp
@@ -0,0 +1,2 @@
+#define __BIONIC_LP32_USE_LONG_DOUBLE
+#include "math_test.cpp"
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index b960944..0fc4e50 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -48,6 +48,12 @@
}
}
+#if defined(__BIONIC_LP32_USE_LONG_DOUBLE)
+#define MATH_TEST math_h_force_long_double
+#else
+#define MATH_TEST math_h
+#endif
+
#include "math_data_test.h"
#include <gtest/gtest.h>
@@ -59,7 +65,7 @@
#include <android-base/scopeguard.h>
-float float_subnormal() {
+static float float_subnormal() {
union {
float f;
uint32_t i;
@@ -68,7 +74,7 @@
return u.f;
}
-double double_subnormal() {
+static double double_subnormal() {
union {
double d;
uint64_t i;
@@ -77,7 +83,7 @@
return u.d;
}
-long double ldouble_subnormal() {
+static long double ldouble_subnormal() {
union {
long double e;
unsigned char c[sizeof(long double)];
@@ -96,7 +102,7 @@
return u.e;
}
-TEST(math, fpclassify) {
+TEST(MATH_TEST, fpclassify) {
ASSERT_EQ(FP_INFINITE, fpclassify(INFINITY));
ASSERT_EQ(FP_INFINITE, fpclassify(HUGE_VALF));
ASSERT_EQ(FP_INFINITE, fpclassify(HUGE_VAL));
@@ -119,7 +125,7 @@
ASSERT_EQ(FP_ZERO, fpclassify(0.0L));
}
-TEST(math, isfinite) {
+TEST(MATH_TEST, isfinite) {
ASSERT_TRUE(test_capture_isfinite(123.0f));
ASSERT_TRUE(test_capture_isfinite(123.0));
ASSERT_TRUE(test_capture_isfinite(123.0L));
@@ -128,7 +134,7 @@
ASSERT_FALSE(test_capture_isfinite(HUGE_VALL));
}
-TEST(math, isinf) {
+TEST(MATH_TEST, isinf) {
ASSERT_FALSE(test_capture_isinf(123.0f));
ASSERT_FALSE(test_capture_isinf(123.0));
ASSERT_FALSE(test_capture_isinf(123.0L));
@@ -137,7 +143,7 @@
ASSERT_TRUE(test_capture_isinf(HUGE_VALL));
}
-TEST(math, isnan) {
+TEST(MATH_TEST, isnan) {
ASSERT_FALSE(test_capture_isnan(123.0f));
ASSERT_FALSE(test_capture_isnan(123.0));
ASSERT_FALSE(test_capture_isnan(123.0L));
@@ -146,7 +152,7 @@
ASSERT_TRUE(test_capture_isnan(nanl("")));
}
-TEST(math, isnormal) {
+TEST(MATH_TEST, isnormal) {
ASSERT_TRUE(isnormal(123.0f));
ASSERT_TRUE(isnormal(123.0));
ASSERT_TRUE(isnormal(123.0L));
@@ -156,7 +162,7 @@
}
// TODO: isgreater, isgreaterequals, isless, islessequal, islessgreater, isunordered
-TEST(math, signbit) {
+TEST(MATH_TEST, signbit) {
ASSERT_EQ(0, test_capture_signbit(0.0f));
ASSERT_EQ(0, test_capture_signbit(0.0));
ASSERT_EQ(0, test_capture_signbit(0.0L));
@@ -170,7 +176,7 @@
ASSERT_NE(0, test_capture_signbit(-1.0L));
}
-TEST(math, __fpclassifyd) {
+TEST(MATH_TEST, __fpclassifyd) {
#if defined(__GLIBC__)
#define __fpclassifyd __fpclassify
#endif
@@ -181,7 +187,7 @@
ASSERT_EQ(FP_ZERO, __fpclassifyd(0.0));
}
-TEST(math, __fpclassifyf) {
+TEST(MATH_TEST, __fpclassifyf) {
ASSERT_EQ(FP_INFINITE, __fpclassifyf(HUGE_VALF));
ASSERT_EQ(FP_NAN, __fpclassifyf(nanf("")));
ASSERT_EQ(FP_NORMAL, __fpclassifyf(1.0f));
@@ -189,7 +195,7 @@
ASSERT_EQ(FP_ZERO, __fpclassifyf(0.0f));
}
-TEST(math, __fpclassifyl) {
+TEST(MATH_TEST, __fpclassifyl) {
EXPECT_EQ(FP_INFINITE, __fpclassifyl(HUGE_VALL));
EXPECT_EQ(FP_NAN, __fpclassifyl(nanl("")));
EXPECT_EQ(FP_NORMAL, __fpclassifyl(1.0L));
@@ -197,12 +203,12 @@
EXPECT_EQ(FP_ZERO, __fpclassifyl(0.0L));
}
-TEST(math, finitef) {
+TEST(MATH_TEST, finitef) {
ASSERT_TRUE(finitef(123.0f));
ASSERT_FALSE(finitef(HUGE_VALF));
}
-TEST(math, __isfinite) {
+TEST(MATH_TEST, __isfinite) {
#if defined(__GLIBC__)
#define __isfinite __finite
#endif
@@ -210,7 +216,7 @@
ASSERT_FALSE(__isfinite(HUGE_VAL));
}
-TEST(math, __isfinitef) {
+TEST(MATH_TEST, __isfinitef) {
#if defined(__GLIBC__)
#define __isfinitef __finitef
#endif
@@ -218,7 +224,7 @@
ASSERT_FALSE(__isfinitef(HUGE_VALF));
}
-TEST(math, __isfinitel) {
+TEST(MATH_TEST, __isfinitel) {
#if defined(__GLIBC__)
#define __isfinitel __finitel
#endif
@@ -226,49 +232,49 @@
ASSERT_FALSE(__isfinitel(HUGE_VALL));
}
-TEST(math, finite) {
+TEST(MATH_TEST, finite) {
ASSERT_TRUE(finite(123.0));
ASSERT_FALSE(finite(HUGE_VAL));
}
-TEST(math, isinf_function) {
+TEST(MATH_TEST, isinf_function) {
// The isinf macro deals with all three types; the isinf function is for doubles.
ASSERT_FALSE((isinf)(123.0));
ASSERT_TRUE((isinf)(HUGE_VAL));
}
-TEST(math, __isinff) {
+TEST(MATH_TEST, __isinff) {
ASSERT_FALSE(__isinff(123.0f));
ASSERT_TRUE(__isinff(HUGE_VALF));
}
-TEST(math, __isinfl) {
+TEST(MATH_TEST, __isinfl) {
ASSERT_FALSE(__isinfl(123.0L));
ASSERT_TRUE(__isinfl(HUGE_VALL));
}
-TEST(math, isnan_function) {
+TEST(MATH_TEST, isnan_function) {
// The isnan macro deals with all three types; the isnan function is for doubles.
ASSERT_FALSE((isnan)(123.0));
ASSERT_TRUE((isnan)(nan("")));
}
-TEST(math, __isnanf) {
+TEST(MATH_TEST, __isnanf) {
ASSERT_FALSE(__isnanf(123.0f));
ASSERT_TRUE(__isnanf(nanf("")));
}
-TEST(math, __isnanl) {
+TEST(MATH_TEST, __isnanl) {
ASSERT_FALSE(__isnanl(123.0L));
ASSERT_TRUE(__isnanl(nanl("")));
}
-TEST(math, isnanf) {
+TEST(MATH_TEST, isnanf) {
ASSERT_FALSE(isnanf(123.0f));
ASSERT_TRUE(isnanf(nanf("")));
}
-TEST(math, __isnormal) {
+TEST(MATH_TEST, __isnormal) {
#if defined(__BIONIC__)
ASSERT_TRUE(__isnormal(123.0));
ASSERT_FALSE(__isnormal(double_subnormal()));
@@ -277,7 +283,7 @@
#endif // __BIONIC__
}
-TEST(math, __isnormalf) {
+TEST(MATH_TEST, __isnormalf) {
#if defined(__BIONIC__)
ASSERT_TRUE(__isnormalf(123.0f));
ASSERT_FALSE(__isnormalf(float_subnormal()));
@@ -286,7 +292,7 @@
#endif // __BIONIC__
}
-TEST(math, __isnormall) {
+TEST(MATH_TEST, __isnormall) {
#if defined(__BIONIC__)
ASSERT_TRUE(__isnormall(123.0L));
ASSERT_FALSE(__isnormall(ldouble_subnormal()));
@@ -295,486 +301,486 @@
#endif // __BIONIC__
}
-TEST(math, __signbit) {
+TEST(MATH_TEST, __signbit) {
ASSERT_EQ(0, __signbit(0.0));
ASSERT_EQ(0, __signbit(1.0));
ASSERT_NE(0, __signbit(-1.0));
}
-TEST(math, __signbitf) {
+TEST(MATH_TEST, __signbitf) {
ASSERT_EQ(0, __signbitf(0.0f));
ASSERT_EQ(0, __signbitf(1.0f));
ASSERT_NE(0, __signbitf(-1.0f));
}
-TEST(math, __signbitl) {
+TEST(MATH_TEST, __signbitl) {
ASSERT_EQ(0L, __signbitl(0.0L));
ASSERT_EQ(0L, __signbitl(1.0L));
ASSERT_NE(0L, __signbitl(-1.0L));
}
-TEST(math, acos) {
+TEST(MATH_TEST, acos) {
ASSERT_DOUBLE_EQ(M_PI/2.0, acos(0.0));
}
-TEST(math, acosf) {
+TEST(MATH_TEST, acosf) {
ASSERT_FLOAT_EQ(static_cast<float>(M_PI)/2.0f, acosf(0.0f));
}
-TEST(math, acosl) {
+TEST(MATH_TEST, acosl) {
ASSERT_DOUBLE_EQ(M_PI/2.0L, acosl(0.0L));
}
-TEST(math, asin) {
+TEST(MATH_TEST, asin) {
ASSERT_DOUBLE_EQ(0.0, asin(0.0));
}
-TEST(math, asinf) {
+TEST(MATH_TEST, asinf) {
ASSERT_FLOAT_EQ(0.0f, asinf(0.0f));
}
-TEST(math, asinl) {
+TEST(MATH_TEST, asinl) {
ASSERT_DOUBLE_EQ(0.0L, asinl(0.0L));
}
-TEST(math, atan) {
+TEST(MATH_TEST, atan) {
ASSERT_DOUBLE_EQ(0.0, atan(0.0));
}
-TEST(math, atanf) {
+TEST(MATH_TEST, atanf) {
ASSERT_FLOAT_EQ(0.0f, atanf(0.0f));
}
-TEST(math, atanl) {
+TEST(MATH_TEST, atanl) {
ASSERT_DOUBLE_EQ(0.0L, atanl(0.0L));
}
-TEST(math, atan2) {
+TEST(MATH_TEST, atan2) {
ASSERT_DOUBLE_EQ(0.0, atan2(0.0, 0.0));
}
-TEST(math, atan2f) {
+TEST(MATH_TEST, atan2f) {
ASSERT_FLOAT_EQ(0.0f, atan2f(0.0f, 0.0f));
}
-TEST(math, atan2l) {
+TEST(MATH_TEST, atan2l) {
ASSERT_DOUBLE_EQ(0.0L, atan2l(0.0L, 0.0L));
}
-TEST(math, cos) {
+TEST(MATH_TEST, cos) {
ASSERT_DOUBLE_EQ(1.0, cos(0.0));
}
-TEST(math, cosf) {
+TEST(MATH_TEST, cosf) {
ASSERT_FLOAT_EQ(1.0f, cosf(0.0f));
}
-TEST(math, cosl) {
+TEST(MATH_TEST, cosl) {
ASSERT_DOUBLE_EQ(1.0L, cosl(0.0L));
}
-TEST(math, sin) {
+TEST(MATH_TEST, sin) {
ASSERT_DOUBLE_EQ(0.0, sin(0.0));
}
-TEST(math, sinf) {
+TEST(MATH_TEST, sinf) {
ASSERT_FLOAT_EQ(0.0f, sinf(0.0f));
}
-TEST(math, sinl) {
+TEST(MATH_TEST, sinl) {
ASSERT_DOUBLE_EQ(0.0L, sinl(0.0L));
}
-TEST(math, sincos) {
+TEST(MATH_TEST, sincos) {
double s, c;
sincos(0.0, &s, &c);
ASSERT_DOUBLE_EQ(0.0, s);
ASSERT_DOUBLE_EQ(1.0, c);
}
-TEST(math, sincosf) {
+TEST(MATH_TEST, sincosf) {
float s, c;
sincosf(0.0f, &s, &c);
ASSERT_FLOAT_EQ(0.0f, s);
ASSERT_FLOAT_EQ(1.0f, c);
}
-TEST(math, sincosl) {
+TEST(MATH_TEST, sincosl) {
long double s, c;
sincosl(0.0L, &s, &c);
ASSERT_DOUBLE_EQ(0.0L, s);
ASSERT_DOUBLE_EQ(1.0L, c);
}
-TEST(math, tan) {
+TEST(MATH_TEST, tan) {
ASSERT_DOUBLE_EQ(0.0, tan(0.0));
}
-TEST(math, tanf) {
+TEST(MATH_TEST, tanf) {
ASSERT_FLOAT_EQ(0.0f, tanf(0.0f));
}
-TEST(math, tanl) {
+TEST(MATH_TEST, tanl) {
ASSERT_DOUBLE_EQ(0.0L, tanl(0.0L));
}
-TEST(math, acosh) {
+TEST(MATH_TEST, acosh) {
ASSERT_DOUBLE_EQ(0.0, acosh(1.0));
}
-TEST(math, acoshf) {
+TEST(MATH_TEST, acoshf) {
ASSERT_FLOAT_EQ(0.0f, acoshf(1.0f));
}
-TEST(math, acoshl) {
+TEST(MATH_TEST, acoshl) {
ASSERT_DOUBLE_EQ(0.0L, acoshl(1.0L));
}
-TEST(math, asinh) {
+TEST(MATH_TEST, asinh) {
ASSERT_DOUBLE_EQ(0.0, asinh(0.0));
}
-TEST(math, asinhf) {
+TEST(MATH_TEST, asinhf) {
ASSERT_FLOAT_EQ(0.0f, asinhf(0.0f));
}
-TEST(math, asinhl) {
+TEST(MATH_TEST, asinhl) {
ASSERT_DOUBLE_EQ(0.0L, asinhl(0.0L));
}
-TEST(math, atanh) {
+TEST(MATH_TEST, atanh) {
ASSERT_DOUBLE_EQ(0.0, atanh(0.0));
}
-TEST(math, atanhf) {
+TEST(MATH_TEST, atanhf) {
ASSERT_FLOAT_EQ(0.0f, atanhf(0.0f));
}
-TEST(math, atanhl) {
+TEST(MATH_TEST, atanhl) {
ASSERT_DOUBLE_EQ(0.0L, atanhl(0.0L));
}
-TEST(math, cosh) {
+TEST(MATH_TEST, cosh) {
ASSERT_DOUBLE_EQ(1.0, cosh(0.0));
}
-TEST(math, coshf) {
+TEST(MATH_TEST, coshf) {
ASSERT_FLOAT_EQ(1.0f, coshf(0.0f));
}
-TEST(math, coshl) {
+TEST(MATH_TEST, coshl) {
ASSERT_DOUBLE_EQ(1.0L, coshl(0.0L));
}
-TEST(math, sinh) {
+TEST(MATH_TEST, sinh) {
ASSERT_DOUBLE_EQ(0.0, sinh(0.0));
}
-TEST(math, sinhf) {
+TEST(MATH_TEST, sinhf) {
ASSERT_FLOAT_EQ(0.0f, sinhf(0.0f));
}
-TEST(math, sinhl) {
+TEST(MATH_TEST, sinhl) {
ASSERT_DOUBLE_EQ(0.0L, sinhl(0.0L));
}
-TEST(math, tanh) {
+TEST(MATH_TEST, tanh) {
ASSERT_DOUBLE_EQ(0.0, tanh(0.0));
}
-TEST(math, tanhf) {
+TEST(MATH_TEST, tanhf) {
ASSERT_FLOAT_EQ(0.0f, tanhf(0.0f));
}
-TEST(math, tanhl) {
+TEST(MATH_TEST, tanhl) {
ASSERT_DOUBLE_EQ(0.0L, tanhl(0.0L));
}
-TEST(math, log) {
+TEST(MATH_TEST, log) {
ASSERT_DOUBLE_EQ(1.0, log(M_E));
}
-TEST(math, logf) {
+TEST(MATH_TEST, logf) {
ASSERT_FLOAT_EQ(1.0f, logf(static_cast<float>(M_E)));
}
-TEST(math, logl) {
+TEST(MATH_TEST, logl) {
ASSERT_DOUBLE_EQ(1.0L, logl(M_E));
}
-TEST(math, log2) {
+TEST(MATH_TEST, log2) {
ASSERT_DOUBLE_EQ(12.0, log2(4096.0));
}
-TEST(math, log2f) {
+TEST(MATH_TEST, log2f) {
ASSERT_FLOAT_EQ(12.0f, log2f(4096.0f));
}
-TEST(math, log2l) {
+TEST(MATH_TEST, log2l) {
ASSERT_DOUBLE_EQ(12.0L, log2l(4096.0L));
}
-TEST(math, log10) {
+TEST(MATH_TEST, log10) {
ASSERT_DOUBLE_EQ(3.0, log10(1000.0));
}
-TEST(math, log10f) {
+TEST(MATH_TEST, log10f) {
ASSERT_FLOAT_EQ(3.0f, log10f(1000.0f));
}
-TEST(math, log10l) {
+TEST(MATH_TEST, log10l) {
ASSERT_DOUBLE_EQ(3.0L, log10l(1000.0L));
}
-TEST(math, cbrt) {
+TEST(MATH_TEST, cbrt) {
ASSERT_DOUBLE_EQ(3.0, cbrt(27.0));
}
-TEST(math, cbrtf) {
+TEST(MATH_TEST, cbrtf) {
ASSERT_FLOAT_EQ(3.0f, cbrtf(27.0f));
}
-TEST(math, cbrtl) {
+TEST(MATH_TEST, cbrtl) {
ASSERT_DOUBLE_EQ(3.0L, cbrtl(27.0L));
}
-TEST(math, sqrt) {
+TEST(MATH_TEST, sqrt) {
ASSERT_DOUBLE_EQ(2.0, sqrt(4.0));
}
-TEST(math, sqrtf) {
+TEST(MATH_TEST, sqrtf) {
ASSERT_FLOAT_EQ(2.0f, sqrtf(4.0f));
}
-TEST(math, sqrtl) {
+TEST(MATH_TEST, sqrtl) {
ASSERT_DOUBLE_EQ(2.0L, sqrtl(4.0L));
}
-TEST(math, exp) {
+TEST(MATH_TEST, exp) {
ASSERT_DOUBLE_EQ(1.0, exp(0.0));
ASSERT_DOUBLE_EQ(M_E, exp(1.0));
}
-TEST(math, expf) {
+TEST(MATH_TEST, expf) {
ASSERT_FLOAT_EQ(1.0f, expf(0.0f));
ASSERT_FLOAT_EQ(static_cast<float>(M_E), expf(1.0f));
}
-TEST(math, expl) {
+TEST(MATH_TEST, expl) {
ASSERT_DOUBLE_EQ(1.0L, expl(0.0L));
ASSERT_DOUBLE_EQ(M_E, expl(1.0L));
}
-TEST(math, exp2) {
+TEST(MATH_TEST, exp2) {
ASSERT_DOUBLE_EQ(8.0, exp2(3.0));
}
-TEST(math, exp2f) {
+TEST(MATH_TEST, exp2f) {
ASSERT_FLOAT_EQ(8.0f, exp2f(3.0f));
}
-TEST(math, exp2l) {
+TEST(MATH_TEST, exp2l) {
ASSERT_DOUBLE_EQ(8.0L, exp2l(3.0L));
}
-TEST(math, expm1) {
+TEST(MATH_TEST, expm1) {
ASSERT_DOUBLE_EQ(M_E - 1.0, expm1(1.0));
}
-TEST(math, expm1f) {
+TEST(MATH_TEST, expm1f) {
ASSERT_FLOAT_EQ(static_cast<float>(M_E) - 1.0f, expm1f(1.0f));
}
-TEST(math, expm1l) {
+TEST(MATH_TEST, expm1l) {
ASSERT_DOUBLE_EQ(M_E - 1.0L, expm1l(1.0L));
}
-TEST(math, pow) {
+TEST(MATH_TEST, pow) {
ASSERT_TRUE(isnan(pow(nan(""), 3.0)));
ASSERT_DOUBLE_EQ(1.0, (pow(1.0, nan(""))));
ASSERT_TRUE(isnan(pow(2.0, nan(""))));
ASSERT_DOUBLE_EQ(8.0, pow(2.0, 3.0));
}
-TEST(math, powf) {
+TEST(MATH_TEST, powf) {
ASSERT_TRUE(isnanf(powf(nanf(""), 3.0f)));
ASSERT_FLOAT_EQ(1.0f, (powf(1.0f, nanf(""))));
ASSERT_TRUE(isnanf(powf(2.0f, nanf(""))));
ASSERT_FLOAT_EQ(8.0f, powf(2.0f, 3.0f));
}
-TEST(math, powl) {
+TEST(MATH_TEST, powl) {
ASSERT_TRUE(__isnanl(powl(nanl(""), 3.0L)));
ASSERT_DOUBLE_EQ(1.0L, (powl(1.0L, nanl(""))));
ASSERT_TRUE(__isnanl(powl(2.0L, nanl(""))));
ASSERT_DOUBLE_EQ(8.0L, powl(2.0L, 3.0L));
}
-TEST(math, ceil) {
+TEST(MATH_TEST, ceil) {
ASSERT_DOUBLE_EQ(1.0, ceil(0.9));
}
-TEST(math, ceilf) {
+TEST(MATH_TEST, ceilf) {
ASSERT_FLOAT_EQ(1.0f, ceilf(0.9f));
}
-TEST(math, ceill) {
+TEST(MATH_TEST, ceill) {
ASSERT_DOUBLE_EQ(1.0L, ceill(0.9L));
}
-TEST(math, floor) {
+TEST(MATH_TEST, floor) {
ASSERT_DOUBLE_EQ(1.0, floor(1.1));
}
-TEST(math, floorf) {
+TEST(MATH_TEST, floorf) {
ASSERT_FLOAT_EQ(1.0f, floorf(1.1f));
}
-TEST(math, floorl) {
+TEST(MATH_TEST, floorl) {
ASSERT_DOUBLE_EQ(1.0L, floorl(1.1L));
}
-TEST(math, fabs) {
+TEST(MATH_TEST, fabs) {
ASSERT_DOUBLE_EQ(1.0, fabs(-1.0));
}
-TEST(math, fabsf) {
+TEST(MATH_TEST, fabsf) {
ASSERT_FLOAT_EQ(1.0f, fabsf(-1.0f));
}
-TEST(math, fabsl) {
+TEST(MATH_TEST, fabsl) {
ASSERT_DOUBLE_EQ(1.0L, fabsl(-1.0L));
}
-TEST(math, ldexp) {
+TEST(MATH_TEST, ldexp) {
ASSERT_DOUBLE_EQ(16.0, ldexp(2.0, 3.0));
}
-TEST(math, ldexpf) {
+TEST(MATH_TEST, ldexpf) {
ASSERT_FLOAT_EQ(16.0f, ldexpf(2.0f, 3.0f));
}
-TEST(math, ldexpl) {
+TEST(MATH_TEST, ldexpl) {
ASSERT_DOUBLE_EQ(16.0L, ldexpl(2.0L, 3.0));
}
-TEST(math, fmod) {
+TEST(MATH_TEST, fmod) {
ASSERT_DOUBLE_EQ(2.0, fmod(12.0, 10.0));
}
-TEST(math, fmodf) {
+TEST(MATH_TEST, fmodf) {
ASSERT_FLOAT_EQ(2.0f, fmodf(12.0f, 10.0f));
}
-TEST(math, fmodl) {
+TEST(MATH_TEST, fmodl) {
ASSERT_DOUBLE_EQ(2.0L, fmodl(12.0L, 10.0L));
}
-TEST(math, remainder) {
+TEST(MATH_TEST, remainder) {
ASSERT_DOUBLE_EQ(2.0, remainder(12.0, 10.0));
}
-TEST(math, remainderf) {
+TEST(MATH_TEST, remainderf) {
ASSERT_FLOAT_EQ(2.0f, remainderf(12.0f, 10.0f));
}
-TEST(math, remainderl) {
+TEST(MATH_TEST, remainderl) {
ASSERT_DOUBLE_EQ(2.0L, remainderl(12.0L, 10.0L));
}
-TEST(math, drem) {
+TEST(MATH_TEST, drem) {
ASSERT_DOUBLE_EQ(2.0, drem(12.0, 10.0));
}
-TEST(math, dremf) {
+TEST(MATH_TEST, dremf) {
ASSERT_FLOAT_EQ(2.0f, dremf(12.0f, 10.0f));
}
-TEST(math, fmax) {
+TEST(MATH_TEST, fmax) {
ASSERT_DOUBLE_EQ(12.0, fmax(12.0, 10.0));
ASSERT_DOUBLE_EQ(12.0, fmax(12.0, nan("")));
ASSERT_DOUBLE_EQ(12.0, fmax(nan(""), 12.0));
}
-TEST(math, fmaxf) {
+TEST(MATH_TEST, fmaxf) {
ASSERT_FLOAT_EQ(12.0f, fmaxf(12.0f, 10.0f));
ASSERT_FLOAT_EQ(12.0f, fmaxf(12.0f, nanf("")));
ASSERT_FLOAT_EQ(12.0f, fmaxf(nanf(""), 12.0f));
}
-TEST(math, fmaxl) {
+TEST(MATH_TEST, fmaxl) {
ASSERT_DOUBLE_EQ(12.0L, fmaxl(12.0L, 10.0L));
ASSERT_DOUBLE_EQ(12.0L, fmaxl(12.0L, nanl("")));
ASSERT_DOUBLE_EQ(12.0L, fmaxl(nanl(""), 12.0L));
}
-TEST(math, fmin) {
+TEST(MATH_TEST, fmin) {
ASSERT_DOUBLE_EQ(10.0, fmin(12.0, 10.0));
ASSERT_DOUBLE_EQ(12.0, fmin(12.0, nan("")));
ASSERT_DOUBLE_EQ(12.0, fmin(nan(""), 12.0));
}
-TEST(math, fminf) {
+TEST(MATH_TEST, fminf) {
ASSERT_FLOAT_EQ(10.0f, fminf(12.0f, 10.0f));
ASSERT_FLOAT_EQ(12.0f, fminf(12.0f, nanf("")));
ASSERT_FLOAT_EQ(12.0f, fminf(nanf(""), 12.0f));
}
-TEST(math, fminl) {
+TEST(MATH_TEST, fminl) {
ASSERT_DOUBLE_EQ(10.0L, fminl(12.0L, 10.0L));
ASSERT_DOUBLE_EQ(12.0L, fminl(12.0L, nanl("")));
ASSERT_DOUBLE_EQ(12.0L, fminl(nanl(""), 12.0L));
}
-TEST(math, fma) {
+TEST(MATH_TEST, fma) {
ASSERT_DOUBLE_EQ(10.0, fma(2.0, 3.0, 4.0));
}
-TEST(math, fmaf) {
+TEST(MATH_TEST, fmaf) {
ASSERT_FLOAT_EQ(10.0f, fmaf(2.0f, 3.0f, 4.0f));
}
-TEST(math, fmal) {
+TEST(MATH_TEST, fmal) {
ASSERT_DOUBLE_EQ(10.0L, fmal(2.0L, 3.0L, 4.0L));
}
-TEST(math, hypot) {
+TEST(MATH_TEST, hypot) {
ASSERT_DOUBLE_EQ(5.0, hypot(3.0, 4.0));
}
-TEST(math, hypotf) {
+TEST(MATH_TEST, hypotf) {
ASSERT_FLOAT_EQ(5.0f, hypotf(3.0f, 4.0f));
}
-TEST(math, hypotl) {
+TEST(MATH_TEST, hypotl) {
ASSERT_DOUBLE_EQ(5.0L, hypotl(3.0L, 4.0L));
}
-TEST(math, erf) {
+TEST(MATH_TEST, erf) {
ASSERT_DOUBLE_EQ(0.84270079294971489, erf(1.0));
}
-TEST(math, erff) {
+TEST(MATH_TEST, erff) {
ASSERT_FLOAT_EQ(0.84270078f, erff(1.0f));
}
-TEST(math, erfl) {
+TEST(MATH_TEST, erfl) {
ASSERT_DOUBLE_EQ(0.84270079294971489L, erfl(1.0L));
}
-TEST(math, erfc) {
+TEST(MATH_TEST, erfc) {
ASSERT_DOUBLE_EQ(0.15729920705028513, erfc(1.0));
}
-TEST(math, erfcf) {
+TEST(MATH_TEST, erfcf) {
ASSERT_FLOAT_EQ(0.15729921f, erfcf(1.0f));
}
-TEST(math, erfcl) {
+TEST(MATH_TEST, erfcl) {
ASSERT_DOUBLE_EQ(0.15729920705028513l, erfcl(1.0L));
}
-TEST(math, lrint) {
+TEST(MATH_TEST, lrint) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // lrint/lrintf/lrintl obey the rounding mode.
@@ -796,7 +802,7 @@
ASSERT_EQ(1234L, llrintl(1234.01L));
}
-TEST(math, rint) {
+TEST(MATH_TEST, rint) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // rint/rintf/rintl obey the rounding mode.
@@ -824,7 +830,7 @@
ASSERT_EQ(1234.0, rintl(1234.01L));
}
-TEST(math, nearbyint) {
+TEST(MATH_TEST, nearbyint) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // nearbyint/nearbyintf/nearbyintl obey the rounding mode.
feclearexcept(FE_ALL_EXCEPT); // nearbyint/nearbyintf/nearbyintl don't set the FE_INEXACT flag.
@@ -851,7 +857,7 @@
ASSERT_EQ(1234.0, nearbyintl(1234.01L));
}
-TEST(math, lround) {
+TEST(MATH_TEST, lround) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // lround ignores the rounding mode.
ASSERT_EQ(1234, lround(1234.01));
@@ -859,7 +865,7 @@
ASSERT_EQ(1234, lroundl(1234.01L));
}
-TEST(math, llround) {
+TEST(MATH_TEST, llround) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // llround ignores the rounding mode.
ASSERT_EQ(1234L, llround(1234.01));
@@ -867,7 +873,7 @@
ASSERT_EQ(1234L, llroundl(1234.01L));
}
-TEST(math, ilogb) {
+TEST(MATH_TEST, ilogb) {
ASSERT_EQ(FP_ILOGB0, ilogb(0.0));
ASSERT_EQ(FP_ILOGBNAN, ilogb(nan("")));
ASSERT_EQ(INT_MAX, ilogb(HUGE_VAL));
@@ -875,7 +881,7 @@
ASSERT_EQ(3, ilogb(10.0));
}
-TEST(math, ilogbf) {
+TEST(MATH_TEST, ilogbf) {
ASSERT_EQ(FP_ILOGB0, ilogbf(0.0f));
ASSERT_EQ(FP_ILOGBNAN, ilogbf(nanf("")));
ASSERT_EQ(INT_MAX, ilogbf(HUGE_VALF));
@@ -883,7 +889,7 @@
ASSERT_EQ(3, ilogbf(10.0f));
}
-TEST(math, ilogbl) {
+TEST(MATH_TEST, ilogbl) {
ASSERT_EQ(FP_ILOGB0, ilogbl(0.0L));
ASSERT_EQ(FP_ILOGBNAN, ilogbl(nanl("")));
ASSERT_EQ(INT_MAX, ilogbl(HUGE_VALL));
@@ -891,7 +897,7 @@
ASSERT_EQ(3L, ilogbl(10.0L));
}
-TEST(math, logb) {
+TEST(MATH_TEST, logb) {
ASSERT_EQ(-HUGE_VAL, logb(0.0));
ASSERT_TRUE(isnan(logb(nan(""))));
ASSERT_TRUE(isinf(logb(HUGE_VAL)));
@@ -899,7 +905,7 @@
ASSERT_EQ(3.0, logb(10.0));
}
-TEST(math, logbf) {
+TEST(MATH_TEST, logbf) {
ASSERT_EQ(-HUGE_VALF, logbf(0.0f));
ASSERT_TRUE(isnanf(logbf(nanf(""))));
ASSERT_TRUE(__isinff(logbf(HUGE_VALF)));
@@ -907,7 +913,7 @@
ASSERT_EQ(3.0f, logbf(10.0f));
}
-TEST(math, logbl) {
+TEST(MATH_TEST, logbl) {
ASSERT_EQ(-HUGE_VAL, logbl(0.0L));
ASSERT_TRUE(isnan(logbl(nanl(""))));
ASSERT_TRUE(isinf(logbl(HUGE_VALL)));
@@ -915,46 +921,46 @@
ASSERT_EQ(3.0L, logbl(10.0L));
}
-TEST(math, log1p) {
+TEST(MATH_TEST, log1p) {
ASSERT_EQ(-HUGE_VAL, log1p(-1.0));
ASSERT_TRUE(isnan(log1p(nan(""))));
ASSERT_TRUE(isinf(log1p(HUGE_VAL)));
ASSERT_DOUBLE_EQ(1.0, log1p(M_E - 1.0));
}
-TEST(math, log1pf) {
+TEST(MATH_TEST, log1pf) {
ASSERT_EQ(-HUGE_VALF, log1pf(-1.0f));
ASSERT_TRUE(isnanf(log1pf(nanf(""))));
ASSERT_TRUE(__isinff(log1pf(HUGE_VALF)));
ASSERT_FLOAT_EQ(1.0f, log1pf(static_cast<float>(M_E) - 1.0f));
}
-TEST(math, log1pl) {
+TEST(MATH_TEST, log1pl) {
ASSERT_EQ(-HUGE_VALL, log1pl(-1.0L));
ASSERT_TRUE(isnan(log1pl(nanl(""))));
ASSERT_TRUE(isinf(log1pl(HUGE_VALL)));
ASSERT_DOUBLE_EQ(1.0L, log1pl(M_E - 1.0L));
}
-TEST(math, fdim) {
+TEST(MATH_TEST, fdim) {
ASSERT_DOUBLE_EQ(0.0, fdim(1.0, 1.0));
ASSERT_DOUBLE_EQ(1.0, fdim(2.0, 1.0));
ASSERT_DOUBLE_EQ(0.0, fdim(1.0, 2.0));
}
-TEST(math, fdimf) {
+TEST(MATH_TEST, fdimf) {
ASSERT_FLOAT_EQ(0.0f, fdimf(1.0f, 1.0f));
ASSERT_FLOAT_EQ(1.0f, fdimf(2.0f, 1.0f));
ASSERT_FLOAT_EQ(0.0f, fdimf(1.0f, 2.0f));
}
-TEST(math, fdiml) {
+TEST(MATH_TEST, fdiml) {
ASSERT_DOUBLE_EQ(0.0L, fdiml(1.0L, 1.0L));
ASSERT_DOUBLE_EQ(1.0L, fdiml(2.0L, 1.0L));
ASSERT_DOUBLE_EQ(0.0L, fdiml(1.0L, 2.0L));
}
-TEST(math, round) {
+TEST(MATH_TEST, round) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_TOWARDZERO); // round ignores the rounding mode and always rounds away from zero.
ASSERT_DOUBLE_EQ(1.0, round(0.5));
@@ -965,7 +971,7 @@
ASSERT_DOUBLE_EQ(HUGE_VAL, round(HUGE_VAL));
}
-TEST(math, roundf) {
+TEST(MATH_TEST, roundf) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_TOWARDZERO); // roundf ignores the rounding mode and always rounds away from zero.
ASSERT_FLOAT_EQ(1.0f, roundf(0.5f));
@@ -976,7 +982,7 @@
ASSERT_FLOAT_EQ(HUGE_VALF, roundf(HUGE_VALF));
}
-TEST(math, roundl) {
+TEST(MATH_TEST, roundl) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_TOWARDZERO); // roundl ignores the rounding mode and always rounds away from zero.
ASSERT_DOUBLE_EQ(1.0L, roundl(0.5L));
@@ -987,7 +993,7 @@
ASSERT_DOUBLE_EQ(HUGE_VALL, roundl(HUGE_VALL));
}
-TEST(math, trunc) {
+TEST(MATH_TEST, trunc) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // trunc ignores the rounding mode and always rounds toward zero.
ASSERT_DOUBLE_EQ(1.0, trunc(1.5));
@@ -998,7 +1004,7 @@
ASSERT_DOUBLE_EQ(HUGE_VAL, trunc(HUGE_VAL));
}
-TEST(math, truncf) {
+TEST(MATH_TEST, truncf) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // truncf ignores the rounding mode and always rounds toward zero.
ASSERT_FLOAT_EQ(1.0f, truncf(1.5f));
@@ -1009,7 +1015,7 @@
ASSERT_FLOAT_EQ(HUGE_VALF, truncf(HUGE_VALF));
}
-TEST(math, truncl) {
+TEST(MATH_TEST, truncl) {
auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); });
fesetround(FE_UPWARD); // truncl ignores the rounding mode and always rounds toward zero.
ASSERT_DOUBLE_EQ(1.0L, truncl(1.5L));
@@ -1020,19 +1026,19 @@
ASSERT_DOUBLE_EQ(HUGE_VALL, truncl(HUGE_VALL));
}
-TEST(math, nextafter) {
+TEST(MATH_TEST, nextafter) {
ASSERT_DOUBLE_EQ(0.0, nextafter(0.0, 0.0));
ASSERT_DOUBLE_EQ(4.9406564584124654e-324, nextafter(0.0, 1.0));
ASSERT_DOUBLE_EQ(-4.9406564584124654e-324, nextafter(0.0, -1.0));
}
-TEST(math, nextafterf) {
+TEST(MATH_TEST, nextafterf) {
ASSERT_FLOAT_EQ(0.0f, nextafterf(0.0f, 0.0f));
ASSERT_FLOAT_EQ(1.4012985e-45f, nextafterf(0.0f, 1.0f));
ASSERT_FLOAT_EQ(-1.4012985e-45f, nextafterf(0.0f, -1.0f));
}
-TEST(math, nextafterl) {
+TEST(MATH_TEST, nextafterl) {
ASSERT_DOUBLE_EQ(0.0L, nextafterl(0.0L, 0.0L));
// Use a runtime value to accomodate the case when
// sizeof(double) == sizeof(long double)
@@ -1041,19 +1047,19 @@
ASSERT_DOUBLE_EQ(-smallest_positive, nextafterl(0.0L, -1.0L));
}
-TEST(math, nexttoward) {
+TEST(MATH_TEST, nexttoward) {
ASSERT_DOUBLE_EQ(0.0, nexttoward(0.0, 0.0L));
ASSERT_DOUBLE_EQ(4.9406564584124654e-324, nexttoward(0.0, 1.0L));
ASSERT_DOUBLE_EQ(-4.9406564584124654e-324, nexttoward(0.0, -1.0L));
}
-TEST(math, nexttowardf) {
+TEST(MATH_TEST, nexttowardf) {
ASSERT_FLOAT_EQ(0.0f, nexttowardf(0.0f, 0.0L));
ASSERT_FLOAT_EQ(1.4012985e-45f, nexttowardf(0.0f, 1.0L));
ASSERT_FLOAT_EQ(-1.4012985e-45f, nexttowardf(0.0f, -1.0L));
}
-TEST(math, nexttowardl) {
+TEST(MATH_TEST, nexttowardl) {
ASSERT_DOUBLE_EQ(0.0L, nexttowardl(0.0L, 0.0L));
// Use a runtime value to accomodate the case when
// sizeof(double) == sizeof(long double)
@@ -1062,86 +1068,86 @@
ASSERT_DOUBLE_EQ(-smallest_positive, nexttowardl(0.0L, -1.0L));
}
-TEST(math, copysign) {
+TEST(MATH_TEST, copysign) {
ASSERT_DOUBLE_EQ(0.0, copysign(0.0, 1.0));
ASSERT_DOUBLE_EQ(-0.0, copysign(0.0, -1.0));
ASSERT_DOUBLE_EQ(2.0, copysign(2.0, 1.0));
ASSERT_DOUBLE_EQ(-2.0, copysign(2.0, -1.0));
}
-TEST(math, copysignf) {
+TEST(MATH_TEST, copysignf) {
ASSERT_FLOAT_EQ(0.0f, copysignf(0.0f, 1.0f));
ASSERT_FLOAT_EQ(-0.0f, copysignf(0.0f, -1.0f));
ASSERT_FLOAT_EQ(2.0f, copysignf(2.0f, 1.0f));
ASSERT_FLOAT_EQ(-2.0f, copysignf(2.0f, -1.0f));
}
-TEST(math, copysignl) {
+TEST(MATH_TEST, copysignl) {
ASSERT_DOUBLE_EQ(0.0L, copysignl(0.0L, 1.0L));
ASSERT_DOUBLE_EQ(-0.0L, copysignl(0.0L, -1.0L));
ASSERT_DOUBLE_EQ(2.0L, copysignl(2.0L, 1.0L));
ASSERT_DOUBLE_EQ(-2.0L, copysignl(2.0L, -1.0L));
}
-TEST(math, significand) {
+TEST(MATH_TEST, significand) {
ASSERT_DOUBLE_EQ(0.0, significand(0.0));
ASSERT_DOUBLE_EQ(1.2, significand(1.2));
ASSERT_DOUBLE_EQ(1.53125, significand(12.25));
}
-TEST(math, significandf) {
+TEST(MATH_TEST, significandf) {
ASSERT_FLOAT_EQ(0.0f, significandf(0.0f));
ASSERT_FLOAT_EQ(1.2f, significandf(1.2f));
ASSERT_FLOAT_EQ(1.53125f, significandf(12.25f));
}
-TEST(math, significandl) {
+TEST(MATH_TEST, significandl) {
ASSERT_DOUBLE_EQ(0.0L, significandl(0.0L));
ASSERT_DOUBLE_EQ(1.2L, significandl(1.2L));
ASSERT_DOUBLE_EQ(1.53125L, significandl(12.25L));
}
-TEST(math, scalb) {
+TEST(MATH_TEST, scalb) {
ASSERT_DOUBLE_EQ(12.0, scalb(3.0, 2.0));
}
-TEST(math, scalbf) {
+TEST(MATH_TEST, scalbf) {
ASSERT_FLOAT_EQ(12.0f, scalbf(3.0f, 2.0f));
}
-TEST(math, scalbln) {
+TEST(MATH_TEST, scalbln) {
ASSERT_DOUBLE_EQ(12.0, scalbln(3.0, 2L));
}
-TEST(math, scalblnf) {
+TEST(MATH_TEST, scalblnf) {
ASSERT_FLOAT_EQ(12.0f, scalblnf(3.0f, 2L));
}
-TEST(math, scalblnl) {
+TEST(MATH_TEST, scalblnl) {
ASSERT_DOUBLE_EQ(12.0L, scalblnl(3.0L, 2L));
}
-TEST(math, scalbn) {
+TEST(MATH_TEST, scalbn) {
ASSERT_DOUBLE_EQ(12.0, scalbn(3.0, 2));
}
-TEST(math, scalbnf) {
+TEST(MATH_TEST, scalbnf) {
ASSERT_FLOAT_EQ(12.0f, scalbnf(3.0f, 2));
}
-TEST(math, scalbnl) {
+TEST(MATH_TEST, scalbnl) {
ASSERT_DOUBLE_EQ(12.0L, scalbnl(3.0L, 2));
}
-TEST(math, gamma) {
+TEST(MATH_TEST, gamma) {
ASSERT_DOUBLE_EQ(log(24.0), gamma(5.0));
}
-TEST(math, gammaf) {
+TEST(MATH_TEST, gammaf) {
ASSERT_FLOAT_EQ(logf(24.0f), gammaf(5.0f));
}
-TEST(math, gamma_r) {
+TEST(MATH_TEST, gamma_r) {
#if defined(__BIONIC__)
int sign;
ASSERT_DOUBLE_EQ(log(24.0), gamma_r(5.0, &sign));
@@ -1151,7 +1157,7 @@
#endif // __BIONIC__
}
-TEST(math, gammaf_r) {
+TEST(MATH_TEST, gammaf_r) {
#if defined(__BIONIC__)
int sign;
ASSERT_FLOAT_EQ(logf(24.0f), gammaf_r(5.0f, &sign));
@@ -1161,25 +1167,25 @@
#endif // __BIONIC__
}
-TEST(math, lgamma) {
+TEST(MATH_TEST, lgamma) {
ASSERT_DOUBLE_EQ(log(24.0), lgamma(5.0));
}
-TEST(math, lgammaf) {
+TEST(MATH_TEST, lgammaf) {
ASSERT_FLOAT_EQ(logf(24.0f), lgammaf(5.0f));
}
-TEST(math, lgammal) {
+TEST(MATH_TEST, lgammal) {
ASSERT_DOUBLE_EQ(logl(24.0L), lgammal(5.0L));
}
-TEST(math, lgamma_r) {
+TEST(MATH_TEST, lgamma_r) {
int sign;
ASSERT_DOUBLE_EQ(log(24.0), lgamma_r(5.0, &sign));
ASSERT_EQ(1, sign);
}
-TEST(math, lgamma_r_17471883) {
+TEST(MATH_TEST, lgamma_r_17471883) {
int sign;
sign = 0;
@@ -1190,13 +1196,13 @@
ASSERT_EQ(-1, sign);
}
-TEST(math, lgammaf_r) {
+TEST(MATH_TEST, lgammaf_r) {
int sign;
ASSERT_FLOAT_EQ(logf(24.0f), lgammaf_r(5.0f, &sign));
ASSERT_EQ(1, sign);
}
-TEST(math, lgammaf_r_17471883) {
+TEST(MATH_TEST, lgammaf_r_17471883) {
int sign;
sign = 0;
@@ -1207,13 +1213,13 @@
ASSERT_EQ(-1, sign);
}
-TEST(math, lgammal_r) {
+TEST(MATH_TEST, lgammal_r) {
int sign;
ASSERT_DOUBLE_EQ(log(24.0L), lgamma_r(5.0L, &sign));
ASSERT_EQ(1, sign);
}
-TEST(math, lgammal_r_17471883) {
+TEST(MATH_TEST, lgammal_r_17471883) {
int sign;
sign = 0;
@@ -1224,132 +1230,132 @@
ASSERT_EQ(-1, sign);
}
-TEST(math, tgamma) {
+TEST(MATH_TEST, tgamma) {
ASSERT_DOUBLE_EQ(24.0, tgamma(5.0));
}
-TEST(math, tgammaf) {
+TEST(MATH_TEST, tgammaf) {
ASSERT_FLOAT_EQ(24.0f, tgammaf(5.0f));
}
-TEST(math, tgammal) {
+TEST(MATH_TEST, tgammal) {
ASSERT_DOUBLE_EQ(24.0L, tgammal(5.0L));
}
-TEST(math, j0) {
+TEST(MATH_TEST, j0) {
ASSERT_DOUBLE_EQ(1.0, j0(0.0));
ASSERT_DOUBLE_EQ(0.76519768655796661, j0(1.0));
}
-TEST(math, j0f) {
+TEST(MATH_TEST, j0f) {
ASSERT_FLOAT_EQ(1.0f, j0f(0.0f));
ASSERT_FLOAT_EQ(0.76519769f, j0f(1.0f));
}
-TEST(math, j1) {
+TEST(MATH_TEST, j1) {
ASSERT_DOUBLE_EQ(0.0, j1(0.0));
ASSERT_DOUBLE_EQ(0.44005058574493355, j1(1.0));
}
-TEST(math, j1f) {
+TEST(MATH_TEST, j1f) {
ASSERT_FLOAT_EQ(0.0f, j1f(0.0f));
ASSERT_FLOAT_EQ(0.44005057f, j1f(1.0f));
}
-TEST(math, jn) {
+TEST(MATH_TEST, jn) {
ASSERT_DOUBLE_EQ(0.0, jn(4, 0.0));
ASSERT_DOUBLE_EQ(0.0024766389641099553, jn(4, 1.0));
}
-TEST(math, jnf) {
+TEST(MATH_TEST, jnf) {
ASSERT_FLOAT_EQ(0.0f, jnf(4, 0.0f));
ASSERT_FLOAT_EQ(0.0024766389f, jnf(4, 1.0f));
}
-TEST(math, y0) {
+TEST(MATH_TEST, y0) {
ASSERT_DOUBLE_EQ(-HUGE_VAL, y0(0.0));
ASSERT_DOUBLE_EQ(0.08825696421567697, y0(1.0));
}
-TEST(math, y0f) {
+TEST(MATH_TEST, y0f) {
ASSERT_FLOAT_EQ(-HUGE_VALF, y0f(0.0f));
ASSERT_FLOAT_EQ(0.088256963f, y0f(1.0f));
}
-TEST(math, y1) {
+TEST(MATH_TEST, y1) {
ASSERT_DOUBLE_EQ(-HUGE_VAL, y1(0.0));
ASSERT_DOUBLE_EQ(-0.78121282130028868, y1(1.0));
}
-TEST(math, y1f) {
+TEST(MATH_TEST, y1f) {
ASSERT_FLOAT_EQ(-HUGE_VALF, y1f(0.0f));
ASSERT_FLOAT_EQ(-0.78121281f, y1f(1.0f));
}
-TEST(math, yn) {
+TEST(MATH_TEST, yn) {
ASSERT_DOUBLE_EQ(-HUGE_VAL, yn(4, 0.0));
ASSERT_DOUBLE_EQ(-33.278423028972114, yn(4, 1.0));
}
-TEST(math, ynf) {
+TEST(MATH_TEST, ynf) {
ASSERT_FLOAT_EQ(-HUGE_VALF, ynf(4, 0.0f));
ASSERT_FLOAT_EQ(-33.278423f, ynf(4, 1.0f));
}
-TEST(math, frexp) {
+TEST(MATH_TEST, frexp) {
int exp;
double dr = frexp(1024.0, &exp);
ASSERT_DOUBLE_EQ(1024.0, scalbn(dr, exp));
}
-TEST(math, frexpf) {
+TEST(MATH_TEST, frexpf) {
int exp;
float fr = frexpf(1024.0f, &exp);
ASSERT_FLOAT_EQ(1024.0f, scalbnf(fr, exp));
}
-TEST(math, frexpl) {
+TEST(MATH_TEST, frexpl) {
int exp;
long double ldr = frexpl(1024.0L, &exp);
ASSERT_DOUBLE_EQ(1024.0L, scalbnl(ldr, exp));
}
-TEST(math, modf) {
+TEST(MATH_TEST, modf) {
double di;
double df = modf(123.75, &di);
ASSERT_DOUBLE_EQ(123.0, di);
ASSERT_DOUBLE_EQ(0.75, df);
}
-TEST(math, modff) {
+TEST(MATH_TEST, modff) {
float fi;
float ff = modff(123.75f, &fi);
ASSERT_FLOAT_EQ(123.0f, fi);
ASSERT_FLOAT_EQ(0.75f, ff);
}
-TEST(math, modfl) {
+TEST(MATH_TEST, modfl) {
long double ldi;
long double ldf = modfl(123.75L, &ldi);
ASSERT_DOUBLE_EQ(123.0L, ldi);
ASSERT_DOUBLE_EQ(0.75L, ldf);
}
-TEST(math, remquo) {
+TEST(MATH_TEST, remquo) {
int q;
double d = remquo(13.0, 4.0, &q);
ASSERT_EQ(3, q);
ASSERT_DOUBLE_EQ(1.0, d);
}
-TEST(math, remquof) {
+TEST(MATH_TEST, remquof) {
int q;
float f = remquof(13.0f, 4.0f, &q);
ASSERT_EQ(3, q);
ASSERT_FLOAT_EQ(1.0, f);
}
-TEST(math, remquol) {
+TEST(MATH_TEST, remquol) {
int q;
long double ld = remquol(13.0L, 4.0L, &q);
ASSERT_DOUBLE_EQ(3L, q);
@@ -1357,13 +1363,13 @@
}
// https://code.google.com/p/android/issues/detail?id=6697
-TEST(math, frexpf_public_bug_6697) {
+TEST(MATH_TEST, frexpf_public_bug_6697) {
int exp;
float fr = frexpf(14.1f, &exp);
ASSERT_FLOAT_EQ(14.1f, scalbnf(fr, exp));
}
-TEST(math, exp2_STRICT_ALIGN_OpenBSD_bug) {
+TEST(MATH_TEST, exp2_STRICT_ALIGN_OpenBSD_bug) {
// OpenBSD/x86's libm had a bug here, but it was already fixed in FreeBSD:
// http://svnweb.FreeBSD.org/base/head/lib/msun/src/math_private.h?revision=240827&view=markup
ASSERT_DOUBLE_EQ(5.0, exp2(log2(5)));
@@ -1371,7 +1377,7 @@
ASSERT_DOUBLE_EQ(5.0L, exp2l(log2l(5)));
}
-TEST(math, nextafterl_OpenBSD_bug) {
+TEST(MATH_TEST, nextafterl_OpenBSD_bug) {
// OpenBSD/x86's libm had a bug here.
ASSERT_TRUE(nextafter(1.0, 0.0) - 1.0 < 0.0);
ASSERT_TRUE(nextafterf(1.0f, 0.0f) - 1.0f < 0.0f);
@@ -1379,511 +1385,511 @@
}
#include "math_data/acos_intel_data.h"
-TEST(math, acos_intel) {
+TEST(MATH_TEST, acos_intel) {
DoMathDataTest<1>(g_acos_intel_data, acos);
}
#include "math_data/acosf_intel_data.h"
-TEST(math, acosf_intel) {
+TEST(MATH_TEST, acosf_intel) {
DoMathDataTest<1>(g_acosf_intel_data, acosf);
}
#include "math_data/acosh_intel_data.h"
-TEST(math, acosh_intel) {
+TEST(MATH_TEST, acosh_intel) {
DoMathDataTest<2>(g_acosh_intel_data, acosh);
}
#include "math_data/acoshf_intel_data.h"
-TEST(math, acoshf_intel) {
+TEST(MATH_TEST, acoshf_intel) {
DoMathDataTest<2>(g_acoshf_intel_data, acoshf);
}
#include "math_data/asin_intel_data.h"
-TEST(math, asin_intel) {
+TEST(MATH_TEST, asin_intel) {
DoMathDataTest<1>(g_asin_intel_data, asin);
}
#include "math_data/asinf_intel_data.h"
-TEST(math, asinf_intel) {
+TEST(MATH_TEST, asinf_intel) {
DoMathDataTest<1>(g_asinf_intel_data, asinf);
}
#include "math_data/asinh_intel_data.h"
-TEST(math, asinh_intel) {
+TEST(MATH_TEST, asinh_intel) {
DoMathDataTest<2>(g_asinh_intel_data, asinh);
}
#include "math_data/asinhf_intel_data.h"
-TEST(math, asinhf_intel) {
+TEST(MATH_TEST, asinhf_intel) {
DoMathDataTest<2>(g_asinhf_intel_data, asinhf);
}
#include "math_data/atan2_intel_data.h"
-TEST(math, atan2_intel) {
+TEST(MATH_TEST, atan2_intel) {
DoMathDataTest<2>(g_atan2_intel_data, atan2);
}
#include "math_data/atan2f_intel_data.h"
-TEST(math, atan2f_intel) {
+TEST(MATH_TEST, atan2f_intel) {
DoMathDataTest<2>(g_atan2f_intel_data, atan2f);
}
#include "math_data/atan_intel_data.h"
-TEST(math, atan_intel) {
+TEST(MATH_TEST, atan_intel) {
DoMathDataTest<1>(g_atan_intel_data, atan);
}
#include "math_data/atanf_intel_data.h"
-TEST(math, atanf_intel) {
+TEST(MATH_TEST, atanf_intel) {
DoMathDataTest<1>(g_atanf_intel_data, atanf);
}
#include "math_data/atanh_intel_data.h"
-TEST(math, atanh_intel) {
+TEST(MATH_TEST, atanh_intel) {
DoMathDataTest<2>(g_atanh_intel_data, atanh);
}
#include "math_data/atanhf_intel_data.h"
-TEST(math, atanhf_intel) {
+TEST(MATH_TEST, atanhf_intel) {
DoMathDataTest<2>(g_atanhf_intel_data, atanhf);
}
#include "math_data/cbrt_intel_data.h"
-TEST(math, cbrt_intel) {
+TEST(MATH_TEST, cbrt_intel) {
DoMathDataTest<1>(g_cbrt_intel_data, cbrt);
}
#include "math_data/cbrtf_intel_data.h"
-TEST(math, cbrtf_intel) {
+TEST(MATH_TEST, cbrtf_intel) {
DoMathDataTest<1>(g_cbrtf_intel_data, cbrtf);
}
#include "math_data/ceil_intel_data.h"
-TEST(math, ceil_intel) {
+TEST(MATH_TEST, ceil_intel) {
DoMathDataTest<1>(g_ceil_intel_data, ceil);
}
#include "math_data/ceilf_intel_data.h"
-TEST(math, ceilf_intel) {
+TEST(MATH_TEST, ceilf_intel) {
DoMathDataTest<1>(g_ceilf_intel_data, ceilf);
}
#include "math_data/copysign_intel_data.h"
-TEST(math, copysign_intel) {
+TEST(MATH_TEST, copysign_intel) {
DoMathDataTest<1>(g_copysign_intel_data, copysign);
}
#include "math_data/copysignf_intel_data.h"
-TEST(math, copysignf_intel) {
+TEST(MATH_TEST, copysignf_intel) {
DoMathDataTest<1>(g_copysignf_intel_data, copysignf);
}
#include "math_data/cos_intel_data.h"
-TEST(math, cos_intel) {
+TEST(MATH_TEST, cos_intel) {
DoMathDataTest<1>(g_cos_intel_data, cos);
}
#include "math_data/cosf_intel_data.h"
-TEST(math, cosf_intel) {
+TEST(MATH_TEST, cosf_intel) {
DoMathDataTest<1>(g_cosf_intel_data, cosf);
}
#include "math_data/cosh_intel_data.h"
-TEST(math, cosh_intel) {
+TEST(MATH_TEST, cosh_intel) {
DoMathDataTest<2>(g_cosh_intel_data, cosh);
}
#include "math_data/coshf_intel_data.h"
-TEST(math, coshf_intel) {
+TEST(MATH_TEST, coshf_intel) {
DoMathDataTest<2>(g_coshf_intel_data, coshf);
}
#include "math_data/exp_intel_data.h"
-TEST(math, exp_intel) {
+TEST(MATH_TEST, exp_intel) {
DoMathDataTest<1>(g_exp_intel_data, exp);
}
#include "math_data/expf_intel_data.h"
-TEST(math, expf_intel) {
+TEST(MATH_TEST, expf_intel) {
DoMathDataTest<1>(g_expf_intel_data, expf);
}
#include "math_data/exp2_intel_data.h"
-TEST(math, exp2_intel) {
+TEST(MATH_TEST, exp2_intel) {
DoMathDataTest<1>(g_exp2_intel_data, exp2);
}
#include "math_data/exp2f_intel_data.h"
-TEST(math, exp2f_intel) {
+TEST(MATH_TEST, exp2f_intel) {
DoMathDataTest<1>(g_exp2f_intel_data, exp2f);
}
#include "math_data/expm1_intel_data.h"
-TEST(math, expm1_intel) {
+TEST(MATH_TEST, expm1_intel) {
DoMathDataTest<1>(g_expm1_intel_data, expm1);
}
#include "math_data/expm1f_intel_data.h"
-TEST(math, expm1f_intel) {
+TEST(MATH_TEST, expm1f_intel) {
DoMathDataTest<1>(g_expm1f_intel_data, expm1f);
}
#include "math_data/fabs_intel_data.h"
-TEST(math, fabs_intel) {
+TEST(MATH_TEST, fabs_intel) {
DoMathDataTest<1>(g_fabs_intel_data, fabs);
}
#include "math_data/fabsf_intel_data.h"
-TEST(math, fabsf_intel) {
+TEST(MATH_TEST, fabsf_intel) {
DoMathDataTest<1>(g_fabsf_intel_data, fabsf);
}
#include "math_data/fdim_intel_data.h"
-TEST(math, fdim_intel) {
+TEST(MATH_TEST, fdim_intel) {
DoMathDataTest<1>(g_fdim_intel_data, fdim);
}
#include "math_data/fdimf_intel_data.h"
-TEST(math, fdimf_intel) {
+TEST(MATH_TEST, fdimf_intel) {
DoMathDataTest<1>(g_fdimf_intel_data, fdimf);
}
#include "math_data/floor_intel_data.h"
-TEST(math, floor_intel) {
+TEST(MATH_TEST, floor_intel) {
DoMathDataTest<1>(g_floor_intel_data, floor);
}
#include "math_data/floorf_intel_data.h"
-TEST(math, floorf_intel) {
+TEST(MATH_TEST, floorf_intel) {
DoMathDataTest<1>(g_floorf_intel_data, floorf);
}
#include "math_data/fma_intel_data.h"
-TEST(math, fma_intel) {
+TEST(MATH_TEST, fma_intel) {
DoMathDataTest<1>(g_fma_intel_data, fma);
}
#include "math_data/fmaf_intel_data.h"
-TEST(math, fmaf_intel) {
+TEST(MATH_TEST, fmaf_intel) {
DoMathDataTest<1>(g_fmaf_intel_data, fmaf);
}
#include "math_data/fmax_intel_data.h"
-TEST(math, fmax_intel) {
+TEST(MATH_TEST, fmax_intel) {
DoMathDataTest<1>(g_fmax_intel_data, fmax);
}
#include "math_data/fmaxf_intel_data.h"
-TEST(math, fmaxf_intel) {
+TEST(MATH_TEST, fmaxf_intel) {
DoMathDataTest<1>(g_fmaxf_intel_data, fmaxf);
}
#include "math_data/fmin_intel_data.h"
-TEST(math, fmin_intel) {
+TEST(MATH_TEST, fmin_intel) {
DoMathDataTest<1>(g_fmin_intel_data, fmin);
}
#include "math_data/fminf_intel_data.h"
-TEST(math, fminf_intel) {
+TEST(MATH_TEST, fminf_intel) {
DoMathDataTest<1>(g_fminf_intel_data, fminf);
}
#include "math_data/fmod_intel_data.h"
-TEST(math, fmod_intel) {
+TEST(MATH_TEST, fmod_intel) {
DoMathDataTest<1>(g_fmod_intel_data, fmod);
}
#include "math_data/fmodf_intel_data.h"
-TEST(math, fmodf_intel) {
+TEST(MATH_TEST, fmodf_intel) {
DoMathDataTest<1>(g_fmodf_intel_data, fmodf);
}
#include "math_data/frexp_intel_data.h"
-TEST(math, frexp_intel) {
+TEST(MATH_TEST, frexp_intel) {
DoMathDataTest<1>(g_frexp_intel_data, frexp);
}
#include "math_data/frexpf_intel_data.h"
-TEST(math, frexpf_intel) {
+TEST(MATH_TEST, frexpf_intel) {
DoMathDataTest<1>(g_frexpf_intel_data, frexpf);
}
#include "math_data/hypot_intel_data.h"
-TEST(math, hypot_intel) {
+TEST(MATH_TEST, hypot_intel) {
DoMathDataTest<1>(g_hypot_intel_data, hypot);
}
#include "math_data/hypotf_intel_data.h"
-TEST(math, hypotf_intel) {
+TEST(MATH_TEST, hypotf_intel) {
DoMathDataTest<1>(g_hypotf_intel_data, hypotf);
}
#include "math_data/ilogb_intel_data.h"
-TEST(math, ilogb_intel) {
+TEST(MATH_TEST, ilogb_intel) {
DoMathDataTest<1>(g_ilogb_intel_data, ilogb);
}
#include "math_data/ilogbf_intel_data.h"
-TEST(math, ilogbf_intel) {
+TEST(MATH_TEST, ilogbf_intel) {
DoMathDataTest<1>(g_ilogbf_intel_data, ilogbf);
}
#include "math_data/ldexp_intel_data.h"
-TEST(math, ldexp_intel) {
+TEST(MATH_TEST, ldexp_intel) {
DoMathDataTest<1>(g_ldexp_intel_data, ldexp);
}
#include "math_data/ldexpf_intel_data.h"
-TEST(math, ldexpf_intel) {
+TEST(MATH_TEST, ldexpf_intel) {
DoMathDataTest<1>(g_ldexpf_intel_data, ldexpf);
}
#include "math_data/llrint_intel_data.h"
-TEST(math, llrint_intel) {
+TEST(MATH_TEST, llrint_intel) {
DoMathDataTest<1>(g_llrint_intel_data, llrint);
}
#include "math_data/llrintf_intel_data.h"
-TEST(math, llrintf_intel) {
+TEST(MATH_TEST, llrintf_intel) {
DoMathDataTest<1>(g_llrintf_intel_data, llrintf);
}
#include "math_data/log_intel_data.h"
-TEST(math, log_intel) {
+TEST(MATH_TEST, log_intel) {
DoMathDataTest<1>(g_log_intel_data, log);
}
#include "math_data/logf_intel_data.h"
-TEST(math, logf_intel) {
+TEST(MATH_TEST, logf_intel) {
DoMathDataTest<1>(g_logf_intel_data, logf);
}
#include "math_data/log10_intel_data.h"
-TEST(math, log10_intel) {
+TEST(MATH_TEST, log10_intel) {
DoMathDataTest<1>(g_log10_intel_data, log10);
}
#include "math_data/log10f_intel_data.h"
-TEST(math, log10f_intel) {
+TEST(MATH_TEST, log10f_intel) {
DoMathDataTest<1>(g_log10f_intel_data, log10f);
}
#include "math_data/log1p_intel_data.h"
-TEST(math, log1p_intel) {
+TEST(MATH_TEST, log1p_intel) {
DoMathDataTest<1>(g_log1p_intel_data, log1p);
}
#include "math_data/log1pf_intel_data.h"
-TEST(math, log1pf_intel) {
+TEST(MATH_TEST, log1pf_intel) {
DoMathDataTest<1>(g_log1pf_intel_data, log1pf);
}
#include "math_data/log2_intel_data.h"
-TEST(math, log2_intel) {
+TEST(MATH_TEST, log2_intel) {
DoMathDataTest<1>(g_log2_intel_data, log2);
}
#include "math_data/log2f_intel_data.h"
-TEST(math, log2f_intel) {
+TEST(MATH_TEST, log2f_intel) {
DoMathDataTest<1>(g_log2f_intel_data, log2f);
}
#include "math_data/logb_intel_data.h"
-TEST(math, logb_intel) {
+TEST(MATH_TEST, logb_intel) {
DoMathDataTest<1>(g_logb_intel_data, logb);
}
#include "math_data/logbf_intel_data.h"
-TEST(math, logbf_intel) {
+TEST(MATH_TEST, logbf_intel) {
DoMathDataTest<1>(g_logbf_intel_data, logbf);
}
#include "math_data/lrint_intel_data.h"
-TEST(math, lrint_intel) {
+TEST(MATH_TEST, lrint_intel) {
DoMathDataTest<1>(g_lrint_intel_data, lrint);
}
#include "math_data/lrintf_intel_data.h"
-TEST(math, lrintf_intel) {
+TEST(MATH_TEST, lrintf_intel) {
DoMathDataTest<1>(g_lrintf_intel_data, lrintf);
}
#include "math_data/modf_intel_data.h"
-TEST(math, modf_intel) {
+TEST(MATH_TEST, modf_intel) {
DoMathDataTest<1>(g_modf_intel_data, modf);
}
#include "math_data/modff_intel_data.h"
-TEST(math, modff_intel) {
+TEST(MATH_TEST, modff_intel) {
DoMathDataTest<1>(g_modff_intel_data, modff);
}
#include "math_data/nearbyint_intel_data.h"
-TEST(math, nearbyint_intel) {
+TEST(MATH_TEST, nearbyint_intel) {
DoMathDataTest<1>(g_nearbyint_intel_data, nearbyint);
}
#include "math_data/nearbyintf_intel_data.h"
-TEST(math, nearbyintf_intel) {
+TEST(MATH_TEST, nearbyintf_intel) {
DoMathDataTest<1>(g_nearbyintf_intel_data, nearbyintf);
}
#include "math_data/nextafter_intel_data.h"
-TEST(math, nextafter_intel) {
+TEST(MATH_TEST, nextafter_intel) {
DoMathDataTest<1>(g_nextafter_intel_data, nextafter);
}
#include "math_data/nextafterf_intel_data.h"
-TEST(math, nextafterf_intel) {
+TEST(MATH_TEST, nextafterf_intel) {
DoMathDataTest<1>(g_nextafterf_intel_data, nextafterf);
}
#include "math_data/pow_intel_data.h"
-TEST(math, pow_intel) {
+TEST(MATH_TEST, pow_intel) {
DoMathDataTest<1>(g_pow_intel_data, pow);
}
#include "math_data/powf_intel_data.h"
-TEST(math, powf_intel) {
+TEST(MATH_TEST, powf_intel) {
DoMathDataTest<1>(g_powf_intel_data, powf);
}
#include "math_data/remainder_intel_data.h"
-TEST(math, remainder_intel) {
+TEST(MATH_TEST, remainder_intel) {
DoMathDataTest<1>(g_remainder_intel_data, remainder);
}
#include "math_data/remainderf_intel_data.h"
-TEST(math, remainderf_intel) {
+TEST(MATH_TEST, remainderf_intel) {
DoMathDataTest<1>(g_remainderf_intel_data, remainderf);
}
#include "math_data/remquo_intel_data.h"
-TEST(math, remquo_intel) {
+TEST(MATH_TEST, remquo_intel) {
DoMathDataTest<1>(g_remquo_intel_data, remquo);
}
#include "math_data/remquof_intel_data.h"
-TEST(math, remquof_intel) {
+TEST(MATH_TEST, remquof_intel) {
DoMathDataTest<1>(g_remquof_intel_data, remquof);
}
#include "math_data/rint_intel_data.h"
-TEST(math, rint_intel) {
+TEST(MATH_TEST, rint_intel) {
DoMathDataTest<1>(g_rint_intel_data, rint);
}
#include "math_data/rintf_intel_data.h"
-TEST(math, rintf_intel) {
+TEST(MATH_TEST, rintf_intel) {
DoMathDataTest<1>(g_rintf_intel_data, rintf);
}
#include "math_data/round_intel_data.h"
-TEST(math, round_intel) {
+TEST(MATH_TEST, round_intel) {
DoMathDataTest<1>(g_round_intel_data, round);
}
#include "math_data/roundf_intel_data.h"
-TEST(math, roundf_intel) {
+TEST(MATH_TEST, roundf_intel) {
DoMathDataTest<1>(g_roundf_intel_data, roundf);
}
#include "math_data/scalb_intel_data.h"
-TEST(math, scalb_intel) {
+TEST(MATH_TEST, scalb_intel) {
DoMathDataTest<1>(g_scalb_intel_data, scalb);
}
#include "math_data/scalbf_intel_data.h"
-TEST(math, scalbf_intel) {
+TEST(MATH_TEST, scalbf_intel) {
DoMathDataTest<1>(g_scalbf_intel_data, scalbf);
}
#include "math_data/scalbn_intel_data.h"
-TEST(math, scalbn_intel) {
+TEST(MATH_TEST, scalbn_intel) {
DoMathDataTest<1>(g_scalbn_intel_data, scalbn);
}
#include "math_data/scalbnf_intel_data.h"
-TEST(math, scalbnf_intel) {
+TEST(MATH_TEST, scalbnf_intel) {
DoMathDataTest<1>(g_scalbnf_intel_data, scalbnf);
}
#include "math_data/significand_intel_data.h"
-TEST(math, significand_intel) {
+TEST(MATH_TEST, significand_intel) {
DoMathDataTest<1>(g_significand_intel_data, significand);
}
#include "math_data/significandf_intel_data.h"
-TEST(math, significandf_intel) {
+TEST(MATH_TEST, significandf_intel) {
DoMathDataTest<1>(g_significandf_intel_data, significandf);
}
#include "math_data/sin_intel_data.h"
-TEST(math, sin_intel) {
+TEST(MATH_TEST, sin_intel) {
DoMathDataTest<1>(g_sin_intel_data, sin);
}
#include "math_data/sinf_intel_data.h"
-TEST(math, sinf_intel) {
+TEST(MATH_TEST, sinf_intel) {
DoMathDataTest<1>(g_sinf_intel_data, sinf);
}
#include "math_data/sinh_intel_data.h"
-TEST(math, sinh_intel) {
+TEST(MATH_TEST, sinh_intel) {
DoMathDataTest<2>(g_sinh_intel_data, sinh);
}
#include "math_data/sinhf_intel_data.h"
-TEST(math, sinhf_intel) {
+TEST(MATH_TEST, sinhf_intel) {
DoMathDataTest<2>(g_sinhf_intel_data, sinhf);
}
#include "math_data/sincos_intel_data.h"
-TEST(math, sincos_intel) {
+TEST(MATH_TEST, sincos_intel) {
DoMathDataTest<1>(g_sincos_intel_data, sincos);
}
#include "math_data/sincosf_intel_data.h"
-TEST(math, sincosf_intel) {
+TEST(MATH_TEST, sincosf_intel) {
DoMathDataTest<1>(g_sincosf_intel_data, sincosf);
}
#include "math_data/sqrt_intel_data.h"
-TEST(math, sqrt_intel) {
+TEST(MATH_TEST, sqrt_intel) {
DoMathDataTest<1>(g_sqrt_intel_data, sqrt);
}
#include "math_data/sqrtf_intel_data.h"
-TEST(math, sqrtf_intel) {
+TEST(MATH_TEST, sqrtf_intel) {
DoMathDataTest<1>(g_sqrtf_intel_data, sqrtf);
}
#include "math_data/tan_intel_data.h"
-TEST(math, tan_intel) {
+TEST(MATH_TEST, tan_intel) {
DoMathDataTest<1>(g_tan_intel_data, tan);
}
#include "math_data/tanf_intel_data.h"
-TEST(math, tanf_intel) {
+TEST(MATH_TEST, tanf_intel) {
DoMathDataTest<1>(g_tanf_intel_data, tanf);
}
#include "math_data/tanh_intel_data.h"
-TEST(math, tanh_intel) {
+TEST(MATH_TEST, tanh_intel) {
DoMathDataTest<2>(g_tanh_intel_data, tanh);
}
#include "math_data/tanhf_intel_data.h"
-TEST(math, tanhf_intel) {
+TEST(MATH_TEST, tanhf_intel) {
DoMathDataTest<2>(g_tanhf_intel_data, tanhf);
}
#include "math_data/trunc_intel_data.h"
-TEST(math, trunc_intel) {
+TEST(MATH_TEST, trunc_intel) {
DoMathDataTest<1>(g_trunc_intel_data, trunc);
}
#include "math_data/truncf_intel_data.h"
-TEST(math, truncf_intel) {
+TEST(MATH_TEST, truncf_intel) {
DoMathDataTest<1>(g_truncf_intel_data, truncf);
}
diff --git a/tests/search_test.cpp b/tests/search_test.cpp
index d368f9f..d5ab67c 100644
--- a/tests/search_test.cpp
+++ b/tests/search_test.cpp
@@ -208,3 +208,80 @@
remque(&zero);
}
+
+static void AssertEntry(ENTRY* e, const char* expected_key, const char* expected_data) {
+ ASSERT_TRUE(e != nullptr);
+ ASSERT_STREQ(expected_key, reinterpret_cast<char*>(e->key));
+ ASSERT_STREQ(expected_data, reinterpret_cast<char*>(e->data));
+}
+
+TEST(search, hcreate_hsearch_hdestroy) {
+ ASSERT_NE(0, hcreate(13));
+
+ // Add some initial entries.
+ ENTRY* e;
+ e = hsearch(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("A")}, ENTER);
+ AssertEntry(e, "a", "A");
+ e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = const_cast<char*>("B")}, ENTER);
+ AssertEntry(e, "aa", "B");
+ e = hsearch(ENTRY{.key = const_cast<char*>("aaa"), .data = const_cast<char*>("C")}, ENTER);
+ AssertEntry(e, "aaa", "C");
+
+ // Check missing.
+ e = hsearch(ENTRY{.key = const_cast<char*>("aaaa"), .data = nullptr}, FIND);
+ ASSERT_FALSE(e != nullptr);
+
+ // Check present.
+ e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = nullptr}, FIND);
+ AssertEntry(e, "aa", "B");
+
+ // ENTER with an existing key just returns the existing ENTRY.
+ e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = const_cast<char*>("X")}, ENTER);
+ AssertEntry(e, "aa", "B");
+ e->data = const_cast<char*>("X");
+
+ // Check present and updated.
+ e = hsearch(ENTRY{.key = const_cast<char*>("aa"), .data = nullptr}, FIND);
+ AssertEntry(e, "aa", "X");
+ // But other entries stayed the same.
+ e = hsearch(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND);
+ AssertEntry(e, "a", "A");
+ e = hsearch(ENTRY{.key = const_cast<char*>("aaa"), .data = nullptr}, FIND);
+ AssertEntry(e, "aaa", "C");
+
+ hdestroy();
+}
+
+TEST(search, hcreate_r_hsearch_r_hdestroy_r) {
+ hsearch_data h1 = {};
+ ASSERT_EQ(1, hcreate_r(13, &h1));
+
+ hsearch_data h2 = {};
+ ASSERT_EQ(1, hcreate_r(128, &h2));
+
+ // Add some initial entries.
+ ENTRY* e;
+ ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("A")},
+ ENTER, &e, &h1));
+ AssertEntry(e, "a", "A");
+ ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = const_cast<char*>("B")},
+ ENTER, &e, &h2));
+ AssertEntry(e, "a", "B");
+
+ // Check missing.
+ errno = 0;
+ ASSERT_EQ(0, hsearch_r(ENTRY{.key = const_cast<char*>("b"), .data = nullptr}, FIND, &e, &h1));
+ ASSERT_EQ(ESRCH, errno);
+
+ // Check present.
+ ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h1));
+ AssertEntry(e, "a", "A");
+ ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h2));
+ AssertEntry(e, "a", "B");
+
+ // Destroying one doesn't affect the other.
+ hdestroy_r(&h1);
+ ASSERT_EQ(1, hsearch_r(ENTRY{.key = const_cast<char*>("a"), .data = nullptr}, FIND, &e, &h2));
+ AssertEntry(e, "a", "B");
+ hdestroy_r(&h2);
+}
diff --git a/tests/stdalign_test.cpp b/tests/stdalign_test.cpp
new file mode 100644
index 0000000..fd6b81e
--- /dev/null
+++ b/tests/stdalign_test.cpp
@@ -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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdalign.h>
+
+TEST(stdalign, smoke) {
+#if !defined(__alignas_is_defined) || __alignas_is_defined != 1
+#error __alignas_is_defined
+#endif
+#if !defined(__alignof_is_defined) || __alignof_is_defined != 1
+#error __alignof_is_defined
+#endif
+ ASSERT_EQ(1U, alignof(char));
+ struct alignas(128) S128 {};
+ ASSERT_EQ(128U, alignof(S128));
+}
diff --git a/tests/stdarg_test.cpp b/tests/stdarg_test.cpp
new file mode 100644
index 0000000..3f33dc2
--- /dev/null
+++ b/tests/stdarg_test.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdarg.h>
+
+TEST(stdarg, smoke) {
+#if !defined(va_start)
+#error va_start
+#endif
+#if !defined(va_arg)
+#error va_arg
+#endif
+#if !defined(va_copy)
+#error va_copy
+#endif
+#if !defined(va_end)
+#error va_end
+#endif
+ va_list l __attribute__((__unused__));
+}
diff --git a/tests/stdbool_test.c b/tests/stdbool_test.c
new file mode 100644
index 0000000..cc23f29
--- /dev/null
+++ b/tests/stdbool_test.c
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#include <stdbool.h>
+
+#if !defined(__bool_true_false_are_defined)
+#error __bool_true_false_are_defined
+#endif
+bool stdbool_true = true;
+bool stdbool_false = false;
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 7d2dc20..27495d8 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -650,3 +650,18 @@
TEST(stdlib, strtoumax_smoke) {
CheckStrToInt(strtoumax);
}
+
+TEST(stdlib, abs) {
+ ASSERT_EQ(INT_MAX, abs(-INT_MAX));
+ ASSERT_EQ(INT_MAX, abs(INT_MAX));
+}
+
+TEST(stdlib, labs) {
+ ASSERT_EQ(LONG_MAX, labs(-LONG_MAX));
+ ASSERT_EQ(LONG_MAX, labs(LONG_MAX));
+}
+
+TEST(stdlib, llabs) {
+ ASSERT_EQ(LLONG_MAX, llabs(-LLONG_MAX));
+ ASSERT_EQ(LLONG_MAX, llabs(LLONG_MAX));
+}
diff --git a/tests/stdnoreturn_test.cpp b/tests/stdnoreturn_test.cpp
new file mode 100644
index 0000000..8d6f62f
--- /dev/null
+++ b/tests/stdnoreturn_test.cpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#include <stdnoreturn.h>
+
+#if !defined(__noreturn_is_defined)
+#error __noreturn_is_defined
+#endif
+
+noreturn void stdnoreturn_h_test_function() {
+ for (;;) ;
+}
diff --git a/tests/sys_mman_test.cpp b/tests/sys_mman_test.cpp
index 62401a6..e44bfed 100644
--- a/tests/sys_mman_test.cpp
+++ b/tests/sys_mman_test.cpp
@@ -235,7 +235,7 @@
TEST(sys_mman, mmap_bug_27265969) {
char* base = reinterpret_cast<char*>(mmap(nullptr, PAGE_SIZE * 2, PROT_EXEC | PROT_READ,
- MAP_ANONYMOUS | MAP_PRIVATE, 0, 0));
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
// Some kernels had bugs that would cause segfaults here...
__builtin___clear_cache(base, base + (PAGE_SIZE * 2));
}
diff --git a/tests/tgmath_test.c b/tests/tgmath_test.c
new file mode 100644
index 0000000..f977306
--- /dev/null
+++ b/tests/tgmath_test.c
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#include <tgmath.h>
+
+float complex tgmath_h_test_function() {
+ float complex z = 1 + 0.5*I;
+ return sqrt(z);
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index cd51e1b..8af2263 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -784,6 +784,12 @@
EXPECT_GT(_XOPEN_IOV_MAX, 0);
EXPECT_GT(_XOPEN_UNIX, 0);
+ // In O, the headers still have -1 (even though all the functionality has
+ // been there for a long time). This was fixed in O-DR, but there isn't a
+ // separate CTS for O-DR, so we'll accept both.
+ EXPECT_TRUE(_POSIX_THREAD_PROCESS_SHARED == -1 ||
+ _POSIX_THREAD_PROCESS_SHARED == _POSIX_VERSION);
+
#if defined(__BIONIC__)
// These tests only pass on bionic, as bionic and glibc has different support on these macros.
// Macros like _POSIX_ASYNCHRONOUS_IO are not supported on bionic yet.
diff --git a/tests/utils.h b/tests/utils.h
index 81df350..8638850 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -17,6 +17,7 @@
#ifndef __TEST_UTILS_H
#define __TEST_UTILS_H
+#include <dlfcn.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/types.h>
@@ -43,6 +44,12 @@
#define KNOWN_FAILURE_ON_BIONIC(x) x
#endif
+// bionic's dlsym doesn't work in static binaries, so we can't access icu,
+// so any unicode test case will fail.
+static inline bool have_dl() {
+ return (dlopen("libc.so", 0) != nullptr);
+}
+
#if defined(__linux__)
#include <sys/sysmacros.h>
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index eb23cf3..6f90c6c 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -20,10 +20,11 @@
#include <inttypes.h>
#include <limits.h>
#include <locale.h>
+#include <math.h>
#include <stdint.h>
#include <wchar.h>
-#include "math_data_test.h"
+#include "utils.h"
#define NUM_WCHARS(num_bytes) ((num_bytes)/sizeof(wchar_t))
@@ -899,6 +900,8 @@
}
TEST(wchar, wcwidth_non_spacing_and_enclosing_marks_and_format) {
+ if (!have_dl()) return;
+
EXPECT_EQ(0, wcwidth(0x0300)); // Combining grave.
EXPECT_EQ(0, wcwidth(0x20dd)); // Combining enclosing circle.
EXPECT_EQ(0, wcwidth(0x00ad)); // Soft hyphen (SHY).
@@ -906,6 +909,8 @@
}
TEST(wchar, wcwidth_cjk) {
+ if (!have_dl()) return;
+
EXPECT_EQ(2, wcwidth(0x4e00)); // Start of CJK unified block.
EXPECT_EQ(2, wcwidth(0x9fff)); // End of CJK unified block.
EXPECT_EQ(2, wcwidth(0x3400)); // Start of CJK extension A block.
@@ -915,18 +920,24 @@
}
TEST(wchar, wcwidth_korean_combining_jamo) {
+ if (!have_dl()) return;
+
AssertWcwidthRange(0x1160, 0x1200, 0); // Original range.
EXPECT_EQ(0, wcwidth(0xd7b0)); // Newer.
EXPECT_EQ(0, wcwidth(0xd7cb));
}
TEST(wchar, wcwidth_korean_jeongeul_syllables) {
+ if (!have_dl()) return;
+
EXPECT_EQ(2, wcwidth(0xac00)); // Start of block.
EXPECT_EQ(2, wcwidth(0xd7a3)); // End of defined code points in Unicode 7.
// Undefined characters at the end of the block have width 1.
}
TEST(wchar, wcwidth_kana) {
+ if (!have_dl()) return;
+
// Hiragana (most, not undefined).
AssertWcwidthRange(0x3041, 0x3097, 2);
// Katakana.
@@ -934,22 +945,30 @@
}
TEST(wchar, wcwidth_circled_two_digit_cjk) {
+ if (!have_dl()) return;
+
// Circled two-digit CJK "speed sign" numbers are wide,
// though EastAsianWidth is ambiguous.
AssertWcwidthRange(0x3248, 0x3250, 2);
}
TEST(wchar, wcwidth_hexagrams) {
+ if (!have_dl()) return;
+
// Hexagrams are wide, though EastAsianWidth is neutral.
AssertWcwidthRange(0x4dc0, 0x4e00, 2);
}
TEST(wchar, wcwidth_default_ignorables) {
+ if (!have_dl()) return;
+
AssertWcwidthRange(0xfff0, 0xfff8, 0); // Unassigned by default ignorable.
EXPECT_EQ(0, wcwidth(0xe0000)); // ...through 0xe0fff.
}
TEST(wchar, wcwidth_korean_common_non_syllables) {
+ if (!have_dl()) return;
+
EXPECT_EQ(2, wcwidth(L'ㅜ')); // Korean "crying" emoticon.
EXPECT_EQ(2, wcwidth(L'ㅋ')); // Korean "laughing" emoticon.
}
diff --git a/tests/wctype_test.cpp b/tests/wctype_test.cpp
index 1bc4128..7da53e0 100644
--- a/tests/wctype_test.cpp
+++ b/tests/wctype_test.cpp
@@ -20,6 +20,8 @@
#include <gtest/gtest.h>
+#include "utils.h"
+
class UtfLocale {
public:
UtfLocale() : l(newlocale(LC_ALL, "C.UTF-8", 0)) {}
@@ -27,12 +29,6 @@
locale_t l;
};
-// bionic's dlsym doesn't work in static binaries, so we can't access icu,
-// so any unicode test case will fail.
-static bool have_dl() {
- return (dlopen("libc.so", 0) != nullptr);
-}
-
static void TestIsWideFn(int fn(wint_t),
int fn_l(wint_t, locale_t),
const wchar_t* trues,