Merge "bionic: test: report kernel sha for clock_getcpuclockid failure"
diff --git a/docs/32-bit-abi.md b/docs/32-bit-abi.md
index 5e3ae45..607b5d2 100644
--- a/docs/32-bit-abi.md
+++ b/docs/32-bit-abi.md
@@ -1,8 +1,6 @@
-32-bit ABI bugs
-===============
+# 32-bit ABI bugs
-`off_t` is 32-bit
------------------
+## 32-bit `off_t` and `_FILE_OFFSET_BITS=64`
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.
@@ -34,13 +32,19 @@
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.
+[linker map](libc/libc.map.txt) for full details. Note also that in NDK r16 and
+later, we inline an mmap64 implementation in the headers when you target an API
+before 21 because it's an easy special case that's often needed. This means
+that code using `_FILE_OFFSET_BITS=64` and `mmap` will always compile.
+
+If your code stops compiling when you move to NDK r15 or later, removing any
+definition of `_FILE_OFFSET_BITS=64` will restore the behavior you used to have:
+you'll have a 32-bit `off_t` and use the 32-bit functions.
In the 64-bit ABI, `off_t` is always 64-bit.
-`sigset_t` is too small for real-time signals
----------------------------------------------
+## `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
@@ -49,8 +53,7 @@
In the 64-bit ABI, `sigset_t` is the correct size for every architecture.
-`time_t` is 32-bit
-------------------
+## `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
@@ -58,8 +61,7 @@
In the 64-bit ABI, `time_t` is 64-bit.
-`pthread_mutex_t` is too small for large pids
----------------------------------------------
+## `pthread_mutex_t` is too small for large pids
This doesn't generally affect Android devices, because on devices
`/proc/sys/kernel/pid_max` is usually too small to hit the 16-bit limit,
diff --git a/libc/Android.bp b/libc/Android.bp
index b88c987..3ec75ee 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -2037,6 +2037,22 @@
}
ndk_headers {
+ name: "libc_asm_mips",
+ from: "kernel/uapi/asm-mips",
+ to: "mipsel-linux-android",
+ srcs: ["kernel/uapi/asm-mips/**/*.h"],
+ license: "NOTICE",
+}
+
+ndk_headers {
+ name: "libc_asm_mips64",
+ from: "kernel/uapi/asm-mips",
+ to: "mips64el-linux-android",
+ srcs: ["kernel/uapi/asm-mips/**/*.h"],
+ license: "NOTICE",
+}
+
+ndk_headers {
name: "libc_asm_x86",
from: "kernel/uapi/asm-x86",
to: "i686-linux-android",
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 2d45fc5..e02a371 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -173,6 +173,7 @@
int fseek(FILE* __fp, long __offset, int __whence);
long ftell(FILE* __fp);
+/* See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md */
#if defined(__USE_FILE_OFFSET64)
int fgetpos(FILE* __fp, fpos_t* __pos) __RENAME(fgetpos64) __INTRODUCED_IN(24);
int fsetpos(FILE* __fp, const fpos_t* __pos) __RENAME(fsetpos64) __INTRODUCED_IN(24);
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 833ced0..3cf6723 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -205,25 +205,28 @@
* In our header files we test against __USE_BSD and __USE_GNU.
*/
#if defined(_GNU_SOURCE)
-# define __USE_BSD 1
-# define __USE_GNU 1
+# define __USE_BSD 1
+# define __USE_GNU 1
#endif
#if defined(_BSD_SOURCE)
-# define __USE_BSD 1
+# define __USE_BSD 1
#endif
-/* _FILE_OFFSET_BITS 64 support. */
+/*
+ * _FILE_OFFSET_BITS 64 support.
+ * See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md
+ */
#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
-#define __USE_FILE_OFFSET64 1
+# define __USE_FILE_OFFSET64 1
/*
* Note that __RENAME_IF_FILE_OFFSET64 is only valid if the off_t and off64_t
* functions were both added at the same API level because if you use this,
* you only have one declaration to attach __INTRODUCED_IN to.
*/
-#define __RENAME_IF_FILE_OFFSET64(func) __RENAME(func)
+# define __RENAME_IF_FILE_OFFSET64(func) __RENAME(func)
#else
-#define __RENAME_IF_FILE_OFFSET64(func)
+# define __RENAME_IF_FILE_OFFSET64(func)
#endif
/*
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 028b024..5a7e3c0 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -44,8 +44,9 @@
#define MREMAP_MAYMOVE 1
#define MREMAP_FIXED 2
-#if defined(__USE_FILE_OFFSET64)
/*
+ * See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md
+ *
* mmap64 wasn't really around until L, but we added an inline for it since it
* allows a lot more code to compile with _FILE_OFFSET_BITS=64.
*
@@ -54,17 +55,18 @@
* mmap64 to every translation unit that includes this header. Instead, just
* preserve the old behavior for GCC and emit a useful diagnostic.
*/
+#if defined(__USE_FILE_OFFSET64)
void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset)
-#if !defined(__clang__) && __ANDROID_API__ < __ANDROID_API_L__
- __attribute__((error("mmap is not available with _FILE_OFFSET_BITS=64 when using GCC until "
- "android-21. Either raise your minSdkVersion, disable "
- "_FILE_OFFSET_BITS=64, or switch to Clang.")));
-#else
+# if !defined(__clang__) && __ANDROID_API__ < __ANDROID_API_L__
+ __attribute__((error("mmap is not available with _FILE_OFFSET_BITS=64 when using GCC until "
+ "android-21. Either raise your minSdkVersion, disable "
+ "_FILE_OFFSET_BITS=64, or switch to Clang.")));
+# else
__RENAME(mmap64);
-#endif /* defined(__clang__) */
+# endif
#else
void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset);
-#endif /* defined(__USE_FILE_OFFSET64) */
+#endif
#if __ANDROID_API__ >= __ANDROID_API_L__
void* mmap64(void* __addr, size_t __size, int __prot, int __flags, int __fd, off64_t __offset) __INTRODUCED_IN(21);
diff --git a/libc/include/sys/sendfile.h b/libc/include/sys/sendfile.h
index ecdb76c..97432c0 100644
--- a/libc/include/sys/sendfile.h
+++ b/libc/include/sys/sendfile.h
@@ -34,6 +34,7 @@
__BEGIN_DECLS
+/* See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md */
#if defined(__USE_FILE_OFFSET64)
ssize_t sendfile(int __out_fd, int __in_fd, off_t* __offset, size_t __count) __RENAME(sendfile64) __INTRODUCED_IN(21);
#else
diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h
index 26ad6a5..f07c8fd 100644
--- a/libc/include/sys/types.h
+++ b/libc/include/sys/types.h
@@ -95,12 +95,13 @@
typedef __kernel_time_t __time_t;
typedef __time_t time_t;
+/* This historical accident means that we had a 32-bit off_t on 32-bit architectures. */
+/* See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md */
#if defined(__USE_FILE_OFFSET64) || defined(__LP64__)
typedef int64_t off_t;
typedef off_t loff_t;
typedef loff_t off64_t;
#else
-/* This historical accident means that we had a 32-bit off_t on 32-bit architectures. */
typedef __kernel_off_t off_t;
typedef __kernel_loff_t loff_t;
typedef loff_t off64_t;
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index c60cf80..ef75c84 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -168,16 +168,10 @@
int fsync(int __fd);
int fdatasync(int __fd) __INTRODUCED_IN(9);
-#if defined(__USE_FILE_OFFSET64)
-off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
-#else
-off_t lseek(int __fd, off_t __offset, int __whence);
-#endif
-
-off64_t lseek64(int __fd, off64_t __offset, int __whence);
-
+/* See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md */
#if defined(__USE_FILE_OFFSET64)
int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
+off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset)
__overloadable __RENAME(pread64) __INTRODUCED_IN(12);
ssize_t pwrite(int __fd, const void* __buf, size_t __count, off_t __offset)
@@ -185,6 +179,7 @@
int ftruncate(int __fd, off_t __length) __RENAME(ftruncate64) __INTRODUCED_IN(12);
#else
int truncate(const char* __path, off_t __length);
+off_t lseek(int __fd, off_t __offset, int __whence);
ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset)
__overloadable __RENAME_CLANG(pread);
ssize_t pwrite(int __fd, const void* __buf, size_t __count, off_t __offset)
@@ -193,6 +188,7 @@
#endif
int truncate64(const char* __path, off64_t __length) __INTRODUCED_IN(21);
+off64_t lseek64(int __fd, off64_t __offset, int __whence);
ssize_t pread64(int __fd, void* __buf, size_t __count, off64_t __offset)
__INTRODUCED_IN(12) __overloadable __RENAME_CLANG(pread64);
ssize_t pwrite64(int __fd, const void* __buf, size_t __count, off64_t __offset)
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index d7ba379..4e90668 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -1385,7 +1385,7 @@
exit(0);
}
ASSERT_NE(-1, pid);
- ASSERT_EQ(pid, waitpid(pid, nullptr, 0));
+ ASSERT_EQ(pid, TEMP_FAILURE_RETRY(waitpid(pid, nullptr, 0)));
// Read all of the contents.
std::string actual;
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 3f59a9c..33dbfd9 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -324,7 +324,7 @@
}
int status;
- if (waitpid(pid, &status, 0) != pid) {
+ if (TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)) != pid) {
perror("waitpid");
return false;
}
diff --git a/tests/sys_ptrace_test.cpp b/tests/sys_ptrace_test.cpp
index 78fcf2b..d460dec 100644
--- a/tests/sys_ptrace_test.cpp
+++ b/tests/sys_ptrace_test.cpp
@@ -51,7 +51,7 @@
~ChildGuard() {
kill(pid, SIGKILL);
int status;
- waitpid(pid, &status, 0);
+ TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
}
private:
@@ -184,7 +184,7 @@
ChildGuard guard(child);
int status;
- ASSERT_EQ(child, waitpid(child, &status, __WALL)) << strerror(errno);
+ ASSERT_EQ(child, TEMP_FAILURE_RETRY(waitpid(child, &status, __WALL))) << strerror(errno);
ASSERT_TRUE(WIFSTOPPED(status)) << "Status was: " << status;
ASSERT_EQ(SIGSTOP, WSTOPSIG(status)) << "Status was: " << status;
@@ -196,7 +196,7 @@
set_watchpoint(child, uintptr_t(&data) + offset, size);
ASSERT_EQ(0, ptrace(PTRACE_CONT, child, nullptr, nullptr)) << strerror(errno);
- ASSERT_EQ(child, waitpid(child, &status, __WALL)) << strerror(errno);
+ ASSERT_EQ(child, TEMP_FAILURE_RETRY(waitpid(child, &status, __WALL))) << strerror(errno);
ASSERT_TRUE(WIFSTOPPED(status)) << "Status was: " << status;
ASSERT_EQ(SIGTRAP, WSTOPSIG(status)) << "Status was: " << status;
@@ -364,7 +364,7 @@
ChildGuard guard(child);
int status;
- ASSERT_EQ(child, waitpid(child, &status, __WALL)) << strerror(errno);
+ ASSERT_EQ(child, TEMP_FAILURE_RETRY(waitpid(child, &status, __WALL))) << strerror(errno);
ASSERT_TRUE(WIFSTOPPED(status)) << "Status was: " << status;
ASSERT_EQ(SIGSTOP, WSTOPSIG(status)) << "Status was: " << status;
@@ -376,7 +376,7 @@
set_breakpoint(child);
ASSERT_EQ(0, ptrace(PTRACE_CONT, child, nullptr, nullptr)) << strerror(errno);
- ASSERT_EQ(child, waitpid(child, &status, __WALL)) << strerror(errno);
+ ASSERT_EQ(child, TEMP_FAILURE_RETRY(waitpid(child, &status, __WALL))) << strerror(errno);
ASSERT_TRUE(WIFSTOPPED(status)) << "Status was: " << status;
ASSERT_EQ(SIGTRAP, WSTOPSIG(status)) << "Status was: " << status;
@@ -436,7 +436,7 @@
}
int result;
- pid_t rc = waitpid(tracer, &result, 0);
+ pid_t rc = TEMP_FAILURE_RETRY(waitpid(tracer, &result, 0));
if (rc != tracer) {
printf("waitpid returned %d (%s)\n", rc, strerror(errno));
return false;
@@ -463,7 +463,7 @@
}
int result;
- pid_t rc = waitpid(worker, &result, WNOHANG);
+ pid_t rc = TEMP_FAILURE_RETRY(waitpid(worker, &result, WNOHANG));
if (rc != 0) {
printf("worker exited prematurely\n");
return false;
@@ -471,7 +471,7 @@
worker_pipe_write.reset();
- rc = waitpid(worker, &result, 0);
+ rc = TEMP_FAILURE_RETRY(waitpid(worker, &result, 0));
if (rc != worker) {
printf("waitpid for worker returned %d (%s)\n", rc, strerror(errno));
return false;
@@ -517,9 +517,9 @@
std::this_thread::sleep_for(250ms);
int result;
- ASSERT_EQ(0, waitpid(worker, &result, WNOHANG));
+ ASSERT_EQ(0, TEMP_FAILURE_RETRY(waitpid(worker, &result, WNOHANG)));
ASSERT_TRUE(WaitForTracer());
- ASSERT_EQ(worker, waitpid(worker, &result, 0));
+ ASSERT_EQ(worker, TEMP_FAILURE_RETRY(waitpid(worker, &result, 0)));
}
TEST_F(PtraceResumptionTest, seize) {
diff --git a/tests/utils.h b/tests/utils.h
index ba006f1..410b427 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -29,6 +29,7 @@
#include <regex>
#include <android-base/file.h>
+#include <android-base/macros.h>
#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
@@ -140,7 +141,7 @@
static inline void AssertChildExited(int pid, int expected_exit_status) {
int status;
- ASSERT_EQ(pid, waitpid(pid, &status, 0));
+ ASSERT_EQ(pid, TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)));
if (expected_exit_status >= 0) {
ASSERT_TRUE(WIFEXITED(status));
ASSERT_EQ(expected_exit_status, WEXITSTATUS(status));