Merge "linker: warn about invalid p_align for loadable segments." into main
diff --git a/libc/include/bits/signal_types.h b/libc/include/bits/signal_types.h
index d98901c..41a697e 100644
--- a/libc/include/bits/signal_types.h
+++ b/libc/include/bits/signal_types.h
@@ -34,36 +34,72 @@
#include <linux/signal.h>
#include <sys/types.h>
-/* The arm and x86 kernel header files don't define _NSIG. */
+/**
+ * The highest kernel-supported signal number, plus one.
+ *
+ * In theory this is useful for declaring an array with an entry for each signal.
+ * In practice, that's less useful than it seems because of the real-time
+ * signals and the reserved signals,
+ * and the sig2str() and str2sig() functions cover the most common use case
+ * of translating between signal numbers and signal names.
+ *
+ * Note also that although sigset_t and sigset64_t are the same type on LP64,
+ * on ILP32 only sigset64_t is large enough to refer to the upper 32 signals.
+ * NSIG does _not_ tell you anything about what can be used with sigset_t.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
+#define NSIG 65
+/** A traditional alternative name for NSIG. */
+#define _NSIG 65
+
+/*
+ * We rewrite the kernel's _NSIG to _KERNEL__NSIG
+ * (because the kernel values are off by one from the userspace values),
+ * but the kernel <asm/signal.h> headers define SIGRTMAX in terms of
+ * _KERNEL__NSIG (or _NSIG, in the original kernel source),
+ * so we need to provide a definition here.
+ * (Ideally our uapi header rewriter would just hard-code _KERNEL__NSIG to 64.)
+ */
#ifndef _KERNEL__NSIG
#define _KERNEL__NSIG 64
#endif
-/* Userspace's NSIG is the kernel's _NSIG + 1. */
-#define _NSIG (_KERNEL__NSIG + 1)
-#define NSIG _NSIG
-
typedef int sig_atomic_t;
typedef __sighandler_t sig_t; /* BSD compatibility. */
typedef __sighandler_t sighandler_t; /* glibc compatibility. */
-/* sigset_t is already large enough on LP64, but LP32's sigset_t
- * is just `unsigned long`.
- */
#if defined(__LP64__)
+/**
+ * The kernel LP64 sigset_t is large enough to support all signals;
+ * this typedef is just for source compatibility with code that uses
+ * real-time signals on ILP32.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
typedef sigset_t sigset64_t;
#else
-typedef struct { unsigned long __bits[_KERNEL__NSIG/(8*sizeof(long))]; } sigset64_t;
+/**
+ * The ILP32 sigset_t is only 32 bits, so we need a 64-bit sigset64_t
+ * and associated functions to be able to support the real-time signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
+typedef struct { unsigned long __bits[64/(8*sizeof(long))]; } sigset64_t;
#endif
-/* The kernel's struct sigaction doesn't match the POSIX one. */
+/* The kernel's struct sigaction doesn't match the POSIX one,
+ * so we define struct sigaction ourselves. */
#if defined(__LP64__)
-/* For 64-bit, that's the only problem, and we only need two structs
- * for source compatibility with 32-bit. */
-
#define __SIGACTION_BODY \
int sa_flags; \
union { \
@@ -73,22 +109,49 @@
sigset_t sa_mask; \
void (*sa_restorer)(void); \
+/**
+ * Used with sigaction().
+ *
+ * On LP64, this supports all signals including real-time signals.
+ * On ILP32, this only supports the first 32 signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
struct sigaction { __SIGACTION_BODY };
+/**
+ * Used with sigaction64().
+ *
+ * On LP64, a synonym for struct sigaction for source compatibility with ILP32.
+ * On ILP32, this is needed to support all signals including real-time signals
+ * because struct sigaction only supports the first 32 signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
struct sigaction64 { __SIGACTION_BODY };
#undef __SIGACTION_BODY
#else
-/* For 32-bit, Android's ABIs used a too-small sigset_t that doesn't
- * support RT signals, so we need two different structs.
- */
-
-/* The arm32 kernel headers also pollute the namespace with these,
+/* The arm32 kernel headers pollute the namespace with these,
* but our header scrubber doesn't know how to remove #defines. */
#undef sa_handler
#undef sa_sigaction
+/**
+ * Used with sigaction().
+ *
+ * On LP64, this supports all signals including real-time signals.
+ * On ILP32, this only supports the first 32 signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
struct sigaction {
union {
sighandler_t sa_handler;
@@ -99,6 +162,17 @@
void (*sa_restorer)(void);
};
+/**
+ * Used with sigaction64().
+ *
+ * On LP64, a synonym for struct sigaction for source compatibility with ILP32.
+ * On ILP32, this is needed to support all signals including real-time signals
+ * because struct sigaction only supports the first 32 signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
struct sigaction64 {
union {
sighandler_t sa_handler;
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 5c0ef6d..3220415 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -96,6 +96,12 @@
/** Maximum value of a ssize_t. */
#define SSIZE_MAX LONG_MAX
+/**
+ * POSIX 2024's name for NSIG.
+ * See the NSIG documentation for an explanation and warnings.
+ */
+#define NSIG_MAX 65
+
/** Maximum number of bytes in a multibyte character. */
#define MB_LEN_MAX 4
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 216eaa0..ee71f03 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -53,7 +53,7 @@
TEST_F(DEATHTEST, stpncpy_fortified2) {
foo myfoo;
- int copy_amt = atoi("11");
+ volatile int copy_amt = 11;
ASSERT_FORTIFY(stpncpy(myfoo.a, "01234567890", copy_amt));
}
@@ -65,7 +65,7 @@
TEST_F(DEATHTEST, strncpy_fortified2) {
foo myfoo;
- int copy_amt = atoi("11");
+ volatile int copy_amt = 11;
ASSERT_FORTIFY(strncpy(myfoo.a, "01234567890", copy_amt));
}
@@ -87,13 +87,11 @@
ASSERT_FORTIFY(sprintf(myfoo.a, "0123456789"));
}
-static int vsprintf_helper2(const char *fmt, ...) {
- foo myfoo;
+static int vsprintf_helper2(const char* fmt, ...) {
va_list va;
- int result;
-
va_start(va, fmt);
- result = vsprintf(myfoo.a, fmt, va); // should crash here
+ foo myfoo;
+ int result = vsprintf(myfoo.a, fmt, va); // should crash here
va_end(va);
return result;
}
@@ -106,14 +104,12 @@
ASSERT_FORTIFY(vsprintf_helper2("0123456789"));
}
-static int vsnprintf_helper2(const char *fmt, ...) {
- foo myfoo;
+static int vsnprintf_helper2(const char* fmt, ...) {
va_list va;
- int result;
- size_t size = atoi("11");
-
va_start(va, fmt);
- result = vsnprintf(myfoo.a, size, fmt, va); // should crash here
+ foo myfoo;
+ volatile size_t size = 11;
+ int result = vsnprintf(myfoo.a, size, fmt, va); // should crash here
va_end(va);
return result;
}
@@ -249,7 +245,7 @@
TEST_F(DEATHTEST, strncat_fortified2) {
foo myfoo;
- size_t n = atoi("10"); // avoid compiler optimizations
+ volatile size_t n = 10;
strncpy(myfoo.a, "012345678", n);
ASSERT_FORTIFY(strncat(myfoo.a, "9", n));
}
@@ -257,7 +253,7 @@
TEST_F(DEATHTEST, strncat2_fortified2) {
foo myfoo;
myfoo.a[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
+ volatile size_t n = 10;
ASSERT_FORTIFY(strncat(myfoo.a, "0123456789", n));
}
@@ -265,7 +261,7 @@
foo myfoo;
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
myfoo.b[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
+ volatile size_t n = 10;
ASSERT_FORTIFY(strncat(myfoo.b, myfoo.a, n));
}
@@ -294,7 +290,7 @@
TEST_F(DEATHTEST, bzero_fortified2) {
foo myfoo;
memcpy(myfoo.b, "0123456789", sizeof(myfoo.b));
- size_t n = atoi("11");
+ volatile size_t n = 11;
ASSERT_FORTIFY(bzero(myfoo.b, n));
}
@@ -304,7 +300,7 @@
TEST_F(DEATHTEST, strcpy_fortified) {
#if defined(__BIONIC__)
char buf[10];
- char *orig = strdup("0123456789");
+ char* orig = strdup("0123456789");
ASSERT_FORTIFY(strcpy(buf, orig));
free(orig);
#else // __BIONIC__
@@ -316,7 +312,7 @@
TEST_F(DEATHTEST, strcpy2_fortified) {
#if defined(__BIONIC__)
char buf[0];
- char *orig = strdup("");
+ char* orig = strdup("");
ASSERT_FORTIFY(strcpy(buf, orig));
free(orig);
#else // __BIONIC__
@@ -328,7 +324,7 @@
TEST_F(DEATHTEST, strcpy3_fortified) {
#if defined(__BIONIC__)
char buf[0];
- char *orig = strdup("1");
+ char* orig = strdup("1");
ASSERT_FORTIFY(strcpy(buf, orig));
free(orig);
#else // __BIONIC__
@@ -340,7 +336,7 @@
TEST_F(DEATHTEST, strcpy4_fortified) {
#if defined(__BIONIC__)
char buf[1];
- char *orig = strdup("12");
+ char* orig = strdup("12");
ASSERT_FORTIFY(strcpy(buf, orig));
free(orig);
#else // __BIONIC__
@@ -411,7 +407,7 @@
}
TEST_F(DEATHTEST, sprintf_malloc_fortified) {
- char* buf = (char *) malloc(10);
+ char* buf = static_cast<char*>(malloc(10));
char source_buf[11];
memcpy(source_buf, "1234567890", 11);
ASSERT_FORTIFY(sprintf(buf, "%s", source_buf));
@@ -423,13 +419,11 @@
ASSERT_FORTIFY(sprintf(buf, "aaaaa"));
}
-static int vsprintf_helper(const char *fmt, ...) {
- char buf[10];
+static int vsprintf_helper(const char* fmt, ...) {
va_list va;
- int result;
-
va_start(va, fmt);
- result = vsprintf(buf, fmt, va); // should crash here
+ char buf[10];
+ int result = vsprintf(buf, fmt, va); // should crash here
va_end(va);
return result;
}
@@ -442,14 +436,12 @@
ASSERT_FORTIFY(vsprintf_helper("0123456789"));
}
-static int vsnprintf_helper(const char *fmt, ...) {
- char buf[10];
+static int vsnprintf_helper(const char* fmt, ...) {
va_list va;
- int result;
- size_t size = atoi("11");
-
va_start(va, fmt);
- result = vsnprintf(buf, size, fmt, va); // should crash here
+ char buf[10];
+ volatile size_t size = 11;
+ int result = vsnprintf(buf, size, fmt, va); // should crash here
va_end(va);
return result;
}
@@ -464,7 +456,7 @@
TEST_F(DEATHTEST, strncat_fortified) {
char buf[10];
- size_t n = atoi("10"); // avoid compiler optimizations
+ volatile size_t n = 10;
strncpy(buf, "012345678", n);
ASSERT_FORTIFY(strncat(buf, "9", n));
}
@@ -472,7 +464,7 @@
TEST_F(DEATHTEST, strncat2_fortified) {
char buf[10];
buf[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
+ volatile size_t n = 10;
ASSERT_FORTIFY(strncat(buf, "0123456789", n));
}
@@ -487,7 +479,7 @@
TEST_F(DEATHTEST, memmove_fortified) {
char buf[20];
strcpy(buf, "0123456789");
- size_t n = atoi("10");
+ volatile size_t n = 10;
ASSERT_FORTIFY(memmove(buf + 11, buf, n));
}
@@ -495,13 +487,13 @@
char bufa[10];
char bufb[10];
strcpy(bufa, "012345678");
- size_t n = atoi("11");
+ volatile size_t n = 11;
ASSERT_FORTIFY(memcpy(bufb, bufa, n));
}
TEST_F(DEATHTEST, memset_fortified) {
char buf[10];
- size_t n = atoi("11");
+ volatile size_t n = 11;
ASSERT_FORTIFY(memset(buf, 0, n));
}
@@ -547,23 +539,23 @@
TEST_F(DEATHTEST, bzero_fortified) {
char buf[10];
memcpy(buf, "0123456789", sizeof(buf));
- size_t n = atoi("11");
+ size_t n = 11;
ASSERT_FORTIFY(bzero(buf, n));
}
TEST_F(DEATHTEST, umask_fortified) {
- mode_t mask = atoi("1023"); // 01777 in octal
+ volatile mode_t mask = 01777;
ASSERT_FORTIFY(umask(mask));
}
TEST_F(DEATHTEST, recv_fortified) {
- size_t data_len = atoi("11"); // suppress compiler optimizations
+ volatile size_t data_len = 11;
char buf[10];
ASSERT_FORTIFY(recv(0, buf, data_len, 0));
}
TEST_F(DEATHTEST, send_fortified) {
- size_t data_len = atoi("11"); // suppress compiler optimizations
+ volatile size_t data_len = 11;
char buf[10] = {0};
ASSERT_FORTIFY(send(0, buf, data_len, 0));
}
@@ -583,84 +575,84 @@
TEST_F(DEATHTEST, getcwd_fortified) {
char buf[1];
- size_t ct = atoi("2"); // prevent optimizations
- ASSERT_FORTIFY(getcwd(buf, ct));
+ volatile size_t n = 2;
+ ASSERT_FORTIFY(getcwd(buf, n));
}
TEST_F(DEATHTEST, pread_fortified) {
char buf[1];
- size_t ct = atoi("2"); // prevent optimizations
+ volatile size_t n = 2;
int fd = open("/dev/null", O_RDONLY);
- ASSERT_FORTIFY(pread(fd, buf, ct, 0));
+ ASSERT_FORTIFY(pread(fd, buf, n, 0));
close(fd);
}
TEST_F(DEATHTEST, pread64_fortified) {
char buf[1];
- size_t ct = atoi("2"); // prevent optimizations
+ volatile size_t n = 2;
int fd = open("/dev/null", O_RDONLY);
- ASSERT_FORTIFY(pread64(fd, buf, ct, 0));
+ ASSERT_FORTIFY(pread64(fd, buf, n, 0));
close(fd);
}
TEST_F(DEATHTEST, pwrite_fortified) {
char buf[1] = {0};
- size_t ct = atoi("2"); // prevent optimizations
+ volatile size_t n = 2;
int fd = open("/dev/null", O_WRONLY);
- ASSERT_FORTIFY(pwrite(fd, buf, ct, 0));
+ ASSERT_FORTIFY(pwrite(fd, buf, n, 0));
close(fd);
}
TEST_F(DEATHTEST, pwrite64_fortified) {
char buf[1] = {0};
- size_t ct = atoi("2"); // prevent optimizations
+ volatile size_t n = 2;
int fd = open("/dev/null", O_WRONLY);
- ASSERT_FORTIFY(pwrite64(fd, buf, ct, 0));
+ ASSERT_FORTIFY(pwrite64(fd, buf, n, 0));
close(fd);
}
TEST_F(DEATHTEST, read_fortified) {
char buf[1];
- size_t ct = atoi("2"); // prevent optimizations
+ volatile size_t n = 2;
int fd = open("/dev/null", O_RDONLY);
- ASSERT_FORTIFY(read(fd, buf, ct));
+ ASSERT_FORTIFY(read(fd, buf, n));
close(fd);
}
TEST_F(DEATHTEST, write_fortified) {
char buf[1] = {0};
- size_t ct = atoi("2"); // prevent optimizations
+ volatile size_t n = 2;
int fd = open("/dev/null", O_WRONLY);
- ASSERT_EXIT(write(fd, buf, ct), testing::KilledBySignal(SIGABRT), "");
+ ASSERT_FORTIFY(write(fd, buf, n));
close(fd);
}
TEST_F(DEATHTEST, fread_fortified) {
char buf[1];
- size_t ct = atoi("2"); // prevent optimizations
+ volatile size_t n = 2;
FILE* fp = fopen("/dev/null", "r");
- ASSERT_FORTIFY(fread(buf, 1, ct, fp));
+ ASSERT_FORTIFY(fread(buf, 1, n, fp));
fclose(fp);
}
TEST_F(DEATHTEST, fwrite_fortified) {
char buf[1] = {0};
- size_t ct = atoi("2"); // prevent optimizations
+ volatile size_t n = 2;
FILE* fp = fopen("/dev/null", "w");
- ASSERT_FORTIFY(fwrite(buf, 1, ct, fp));
+ ASSERT_FORTIFY(fwrite(buf, 1, n, fp));
fclose(fp);
}
TEST_F(DEATHTEST, readlink_fortified) {
char buf[1];
- size_t ct = atoi("2"); // prevent optimizations
- ASSERT_FORTIFY(readlink("/dev/null", buf, ct));
+ volatile size_t n = 2;
+ ASSERT_FORTIFY(readlink("/dev/null", buf, n));
}
TEST_F(DEATHTEST, readlinkat_fortified) {
char buf[1];
- size_t ct = atoi("2"); // prevent optimizations
- ASSERT_FORTIFY(readlinkat(AT_FDCWD, "/dev/null", buf, ct));
+ volatile size_t n = 2;
+ ASSERT_FORTIFY(readlinkat(AT_FDCWD, "/dev/null", buf, n));
}
TEST(TEST_NAME, snprintf_nullptr_valid) {
@@ -904,7 +896,8 @@
memset(buf, 'A', sizeof(buf));
buf[0] = 'a';
buf[1] = '\0';
- char* res = __strcat_chk(buf, "01234567", (size_t)-1);
+ volatile size_t n = -1;
+ char* res = __strcat_chk(buf, "01234567", n);
ASSERT_EQ(buf, res);
ASSERT_EQ('a', buf[0]);
ASSERT_EQ('0', buf[1]);
@@ -940,7 +933,8 @@
TEST(TEST_NAME, stpcpy_chk_max_int_size) {
char buf[10];
- char* res = __stpcpy_chk(buf, "012345678", (size_t)-1);
+ volatile size_t n = -1;
+ char* res = __stpcpy_chk(buf, "012345678", n);
ASSERT_EQ(buf + strlen("012345678"), res);
ASSERT_STREQ("012345678", buf);
}
@@ -949,7 +943,8 @@
TEST(TEST_NAME, strcpy_chk_max_int_size) {
char buf[10];
- char* res = __strcpy_chk(buf, "012345678", (size_t)-1);
+ volatile size_t n = -1;
+ char* res = __strcpy_chk(buf, "012345678", n);
ASSERT_EQ(buf, res);
ASSERT_STREQ("012345678", buf);
}
@@ -958,7 +953,7 @@
TEST(TEST_NAME, memcpy_chk_smaller) {
char buf[10] = "XXXXXXXXX";
- size_t n = atoi("5");
+ volatile size_t n = 5;
void* res = __memcpy_chk(buf, "012346578", n, sizeof(buf));
ASSERT_EQ((void*)buf, res);
ASSERT_EQ('0', buf[0]);
@@ -975,7 +970,7 @@
TEST(TEST_NAME, memcpy_chk_exact_size) {
char buf[10] = "XXXXXXXXX";
- size_t n = atoi("10");
+ volatile size_t n = 10;
void* res = __memcpy_chk(buf, "012345678", n, sizeof(buf));
ASSERT_EQ((void*)buf, res);
ASSERT_EQ('0', buf[0]);
@@ -992,8 +987,8 @@
TEST(TEST_NAME, memcpy_chk_max_int_size) {
char buf[10];
- size_t buf_size = atoi("-1");
- void* res = __memcpy_chk(buf, "012345678", sizeof(buf), buf_size);
+ volatile size_t n = -1;
+ void* res = __memcpy_chk(buf, "012345678", sizeof(buf), n);
ASSERT_EQ((void*)buf, res);
ASSERT_EQ('0', buf[0]);
ASSERT_EQ('1', buf[1]);
@@ -1026,38 +1021,36 @@
}
TEST_F(DEATHTEST, poll_fortified) {
- nfds_t fd_count = atoi("2"); // suppress compiler optimizations
+ volatile nfds_t fd_count = 2;
pollfd buf[1] = {{0, POLLIN, 0}};
// Set timeout to zero to prevent waiting in poll when fortify test fails.
ASSERT_FORTIFY(poll(buf, fd_count, 0));
}
TEST_F(DEATHTEST, ppoll_fortified) {
- nfds_t fd_count = atoi("2"); // suppress compiler optimizations
+ volatile nfds_t fd_count = 2;
pollfd buf[1] = {{0, POLLIN, 0}};
- // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
- timespec timeout;
- timeout.tv_sec = timeout.tv_nsec = 0;
+ // Set timeout to zero to prevent waiting in ppoll if fortify test fails.
+ timespec timeout = {};
ASSERT_FORTIFY(ppoll(buf, fd_count, &timeout, nullptr));
}
TEST_F(DEATHTEST, ppoll64_fortified) {
#if defined(__BIONIC__) // glibc doesn't have ppoll64.
- nfds_t fd_count = atoi("2"); // suppress compiler optimizations
+ volatile nfds_t fd_count = 2;
pollfd buf[1] = {{0, POLLIN, 0}};
- // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
- timespec timeout;
- timeout.tv_sec = timeout.tv_nsec = 0;
+ // Set timeout to zero to prevent waiting in ppoll if fortify test fails.
+ timespec timeout= {};
ASSERT_FORTIFY(ppoll64(buf, fd_count, &timeout, nullptr));
#endif
}
TEST_F(DEATHTEST, open_O_CREAT_without_mode_fortified) {
- int flags = O_CREAT; // Fool the compiler.
+ volatile int flags = O_CREAT;
ASSERT_FORTIFY(open("", flags));
}
TEST_F(DEATHTEST, open_O_TMPFILE_without_mode_fortified) {
- int flags = O_TMPFILE; // Fool the compiler.
+ volatile int flags = O_TMPFILE;
ASSERT_FORTIFY(open("", flags));
}
diff --git a/tests/headers/posix/dlfcn_h.c b/tests/headers/posix/dlfcn_h.c
index 4800075..e8dc648 100644
--- a/tests/headers/posix/dlfcn_h.c
+++ b/tests/headers/posix/dlfcn_h.c
@@ -36,6 +36,17 @@
MACRO(RTLD_GLOBAL);
MACRO(RTLD_LOCAL);
+#if !defined(__GLIBC__) // Our glibc is too old.
+ TYPE(Dl_info);
+ STRUCT_MEMBER(Dl_info, const char*, dli_fname);
+ STRUCT_MEMBER(Dl_info, void*, dli_fbase);
+ STRUCT_MEMBER(Dl_info, const char*, dli_sname);
+ STRUCT_MEMBER(Dl_info, void*, dli_saddr);
+#endif
+
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(dladdr, int (*f)(const void*, Dl_info*));
+#endif
FUNCTION(dlclose, int (*f)(void*));
FUNCTION(dlerror, char* (*f)(void));
FUNCTION(dlopen, void* (*f)(const char*, int));
diff --git a/tests/headers/posix/limits_h.c b/tests/headers/posix/limits_h.c
index 0ca80a5..0a3bc1c 100644
--- a/tests/headers/posix/limits_h.c
+++ b/tests/headers/posix/limits_h.c
@@ -58,6 +58,9 @@
#if !defined(__BIONIC__)
MACRO(MQ_PRIO_MAX);
#endif
+#if defined(__BIONIC__)
+ MACRO(NSIG_MAX);
+#endif
#if !defined(__BIONIC__) && !defined(__GLIBC__) && !defined(ANDROID_HOST_MUSL)
MACRO(OPEN_MAX);
#endif
diff --git a/tests/headers/posix/poll_h.c b/tests/headers/posix/poll_h.c
index 4fce5e5..505ba46 100644
--- a/tests/headers/posix/poll_h.c
+++ b/tests/headers/posix/poll_h.c
@@ -36,6 +36,11 @@
STRUCT_MEMBER(struct pollfd, short, events);
STRUCT_MEMBER(struct pollfd, short, revents);
+#if !defined(__GLIBC__) // Our glibc is too old.
+ TYPE(sigset_t);
+ TYPE(struct timespec);
+#endif
+
TYPE(nfds_t);
MACRO(POLLIN);
@@ -50,4 +55,7 @@
MACRO(POLLNVAL);
FUNCTION(poll, int (*f)(struct pollfd[], nfds_t, int));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(ppoll, int (*f)(struct pollfd[], nfds_t, const struct timespec*, const sigset_t*));
+#endif
}
diff --git a/tests/headers/posix/pthread_h.c b/tests/headers/posix/pthread_h.c
index 4be822c..3713aff 100644
--- a/tests/headers/posix/pthread_h.c
+++ b/tests/headers/posix/pthread_h.c
@@ -116,6 +116,9 @@
FUNCTION(pthread_cancel, int (*f)(pthread_t));
#endif
FUNCTION(pthread_cond_broadcast, int (*f)(pthread_cond_t*));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(pthread_cond_clockwait, int (*f)(pthread_cond_t*, pthread_mutex_t*, clockid_t, const struct timespec*));
+#endif
FUNCTION(pthread_cond_destroy, int (*f)(pthread_cond_t*));
FUNCTION(pthread_cond_init, int (*f)(pthread_cond_t*, const pthread_condattr_t*));
FUNCTION(pthread_cond_signal, int (*f)(pthread_cond_t*));
@@ -140,6 +143,9 @@
FUNCTION(pthread_join, int (*f)(pthread_t, void**));
FUNCTION(pthread_key_create, int (*f)(pthread_key_t*, void (*)(void*)));
FUNCTION(pthread_key_delete, int (*f)(pthread_key_t));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(pthread_mutex_clocklock, int (*f)(pthread_mutex_t*, clockid_t, const struct timespec*));
+#endif
#if !defined(__BIONIC__) // No robust mutexes on Android.
FUNCTION(pthread_mutex_consistent, int (*f)(pthread_mutex_t*));
#endif
@@ -176,6 +182,10 @@
#endif
FUNCTION(pthread_mutexattr_settype, int (*f)(pthread_mutexattr_t*, int));
FUNCTION(pthread_once, int (*f)(pthread_once_t*, void (*)(void)));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(pthread_rwlock_clockrdlock, int (*f)(pthread_rwlock_t*, clockid_t, const struct timespec*));
+ FUNCTION(pthread_rwlock_clockwrlock, int (*f)(pthread_rwlock_t*, clockid_t, const struct timespec*));
+#endif
FUNCTION(pthread_rwlock_destroy, int (*f)(pthread_rwlock_t*));
FUNCTION(pthread_rwlock_init, int (*f)(pthread_rwlock_t*, const pthread_rwlockattr_t*));
FUNCTION(pthread_rwlock_rdlock, int (*f)(pthread_rwlock_t*));
diff --git a/tests/headers/posix/semaphore_h.c b/tests/headers/posix/semaphore_h.c
index 9d5c7e1..d813363 100644
--- a/tests/headers/posix/semaphore_h.c
+++ b/tests/headers/posix/semaphore_h.c
@@ -35,6 +35,9 @@
MACRO(SEM_FAILED);
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(sem_clockwait, int (*f)(sem_t*, clockid_t, const struct timespec*));
+#endif
FUNCTION(sem_close, int (*f)(sem_t*));
FUNCTION(sem_destroy, int (*f)(sem_t*));
FUNCTION(sem_getvalue, int (*f)(sem_t*, int*));
diff --git a/tests/headers/posix/signal_h.c b/tests/headers/posix/signal_h.c
index 82751f4..3b50fb9 100644
--- a/tests/headers/posix/signal_h.c
+++ b/tests/headers/posix/signal_h.c
@@ -75,6 +75,10 @@
i = SIGRTMIN;
i = SIGRTMAX;
+#if !defined(__GLIBC__) // Our glibc is too old.
+ MACRO(SIG2STR_MAX);
+#endif
+
MACRO(SIGABRT);
MACRO(SIGALRM);
MACRO(SIGBUS);
diff --git a/tests/headers/posix/stdlib_h.c b/tests/headers/posix/stdlib_h.c
index 95769b4..deedc06 100644
--- a/tests/headers/posix/stdlib_h.c
+++ b/tests/headers/posix/stdlib_h.c
@@ -119,6 +119,9 @@
FUNCTION(rand_r, int (*f)(unsigned*));
FUNCTION(random, long (*f)(void));
FUNCTION(realloc, void* (*f)(void*, size_t));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(reallocarray, void* (*f)(void*, size_t, size_t));
+#endif
FUNCTION(realpath, char* (*f)(const char*, char*));
FUNCTION(seed48, unsigned short* (*f)(unsigned short[3]));
FUNCTION(setenv, int (*f)(const char*, const char*, int));
diff --git a/tests/headers/posix/string_h.c b/tests/headers/posix/string_h.c
index 2440050..59a541f 100644
--- a/tests/headers/posix/string_h.c
+++ b/tests/headers/posix/string_h.c
@@ -39,6 +39,9 @@
FUNCTION(memchr, void* (*f)(const void*, int, size_t));
FUNCTION(memcmp, int (*f)(const void*, const void*, size_t));
FUNCTION(memcpy, void* (*f)(void*, const void*, size_t));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(memmem, void* (*f)(const void*, size_t, const void*, size_t));
+#endif
FUNCTION(memmove, void* (*f)(void*, const void*, size_t));
FUNCTION(memset, void* (*f)(void*, int, size_t));
FUNCTION(stpcpy, char* (*f)(char*, const char*));
@@ -54,6 +57,10 @@
FUNCTION(strerror, char* (*f)(int));
FUNCTION(strerror_l, char* (*f)(int, locale_t));
FUNCTION(strerror_r, int (*f)(int, char*, size_t));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(strlcat, size_t (*f)(char*, const char*, size_t));
+ FUNCTION(strlcpy, size_t (*f)(char*, const char*, size_t));
+#endif
FUNCTION(strlen, size_t (*f)(const char*));
FUNCTION(strncat, char* (*f)(char*, const char*, size_t));
FUNCTION(strncmp, int (*f)(const char*, const char*, size_t));
diff --git a/tests/headers/posix/unistd_h.c b/tests/headers/posix/unistd_h.c
index fdd7bde..e54fbb3 100644
--- a/tests/headers/posix/unistd_h.c
+++ b/tests/headers/posix/unistd_h.c
@@ -342,6 +342,9 @@
FUNCTION(ftruncate, int (*f)(int, off_t));
FUNCTION(getcwd, char* (*f)(char*, size_t));
FUNCTION(getegid, gid_t (*f)(void));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(getentropy, int (*f)(void*, size_t));
+#endif
FUNCTION(geteuid, uid_t (*f)(void));
FUNCTION(getgid, gid_t (*f)(void));
FUNCTION(getgroups, int (*f)(int, gid_t[]));
diff --git a/tests/headers/posix/wchar_h.c b/tests/headers/posix/wchar_h.c
index 48b3b92..26a3473 100644
--- a/tests/headers/posix/wchar_h.c
+++ b/tests/headers/posix/wchar_h.c
@@ -86,6 +86,10 @@
FUNCTION(wcscspn, size_t (*f)(const wchar_t*, const wchar_t*));
FUNCTION(wcsdup, wchar_t* (*f)(const wchar_t*));
FUNCTION(wcsftime, size_t (*f)(wchar_t*, size_t, const wchar_t*, const struct tm*));
+#if !defined(__GLIBC__) // Our glibc is too old.
+ FUNCTION(wcslcat, size_t (*f)(wchar_t*, const wchar_t*, size_t));
+ FUNCTION(wcslcpy, size_t (*f)(wchar_t*, const wchar_t*, size_t));
+#endif
FUNCTION(wcslen, size_t (*f)(const wchar_t*));
FUNCTION(wcsncasecmp, int (*f)(const wchar_t*, const wchar_t*, size_t));
FUNCTION(wcsncasecmp_l, int (*f)(const wchar_t*, const wchar_t*, size_t, locale_t));
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
index bc13a3f..64d9a33 100644
--- a/tests/limits_test.cpp
+++ b/tests/limits_test.cpp
@@ -78,3 +78,11 @@
#error ULLONG_MAX
#endif
}
+
+TEST(limits, highest_signal_plus_one) {
+#if defined(__BIONIC__)
+ ASSERT_EQ(65, NSIG_MAX);
+#endif
+ ASSERT_EQ(65, NSIG);
+ ASSERT_EQ(65, _NSIG);
+}