From e956a8252fc1c9ba79b2c4ff3f4d5baecdd8e390 Mon Sep 17 00:00:00 2001 From: Mark Mentovai Date: Mon, 31 Oct 2016 11:23:00 -0400 Subject: [PATCH] Port the util library to Android MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this change, it is possible to build crashpad_util for Android with clang. I built with NDK 13b (clang 3.8) at API 24 (current), API 21 (used by Chrome in 64-bit builds), and API 16 (used by Chrome in 32-bit builds). - In WeakFileHandleFileWriter::WriteIoVec(): Android does not expose the IOV_MAX macro, but its value can be obtained by calling sysconf(_SC_IOV_MAX). - In CloseMultipleNowOrOnExec(): API 21 removes getdtablesize(). Skip it, because it returned the same thing as sysconf(_SC_OPEN_MAX), which is already consulted. - Throughout: Various #ifdefs checking for OS_LINUX have been extended to also check for OS_ANDROID. In Chrome’s build_config.h (and thus mini_chromium’s), OS_LINUX is not defined when OS_ANDROID is. This has not been tested beyond building the crashpad_util target. BUG=crashpad:30 Change-Id: Ieb0bed736029d2d776c534e30e534f186e6fb663 Reviewed-on: https://chromium-review.googlesource.com/405267 Reviewed-by: Robert Sesek --- util/file/file_writer.cc | 14 ++++++++++++-- util/misc/uuid.cc | 2 +- util/posix/close_multiple.cc | 14 +++++++++++--- util/posix/drop_privileges.cc | 2 +- util/posix/symbolic_constants_posix.cc | 6 +++--- util/posix/symbolic_constants_posix_test.cc | 4 ++-- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/util/file/file_writer.cc b/util/file/file_writer.cc index edbdb8d5..94f41f14 100644 --- a/util/file/file_writer.cc +++ b/util/file/file_writer.cc @@ -73,9 +73,19 @@ bool WeakFileHandleFileWriter::WriteIoVec(std::vector* iovecs) { iovec* iov = reinterpret_cast(&(*iovecs)[0]); size_t remaining_iovecs = iovecs->size(); +#if defined(OS_ANDROID) + // Android does not expose the IOV_MAX macro, but makes its value available + // via sysconf(). See Android 7.0.0 bionic/libc/bionic/sysconf.cpp sysconf(). + // Bionic defines IOV_MAX at bionic/libc/include/limits.h, but does not ship + // this file to the NDK as , substituting + // bionic/libc/include/bits/posix_limits.h. + const size_t kIovMax = sysconf(_SC_IOV_MAX); +#else + const size_t kIovMax = IOV_MAX; +#endif + while (size > 0) { - size_t writev_iovec_count = - std::min(remaining_iovecs, implicit_cast(IOV_MAX)); + size_t writev_iovec_count = std::min(remaining_iovecs, kIovMax); ssize_t written = HANDLE_EINTR(writev(file_handle_, iov, writev_iovec_count)); if (written < 0) { diff --git a/util/misc/uuid.cc b/util/misc/uuid.cc index 21581cf3..e4b4b31a 100644 --- a/util/misc/uuid.cc +++ b/util/misc/uuid.cc @@ -111,7 +111,7 @@ bool UUID::InitializeWithNew() { } InitializeFromSystemUUID(&system_uuid); return true; -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_ANDROID) // Linux does not provide a UUID generator in a widely-available system // library. uuid_generate() from libuuid is not available everywhere. base::RandBytes(this, sizeof(*this)); diff --git a/util/posix/close_multiple.cc b/util/posix/close_multiple.cc index d46cd9db..f1d7773f 100644 --- a/util/posix/close_multiple.cc +++ b/util/posix/close_multiple.cc @@ -88,7 +88,7 @@ using ScopedDIR = std::unique_ptr; bool CloseMultipleNowOrOnExecUsingFDDir(int fd, int preserve_fd) { #if defined(OS_MACOSX) const char kFDDir[] = "/dev/fd"; -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_ANDROID) const char kFDDir[] = "/proc/self/fd"; #endif @@ -167,9 +167,17 @@ void CloseMultipleNowOrOnExec(int fd, int preserve_fd) { // Libc-1082.50.1/gen/FreeBSD/sysconf.c sysconf() and 10.11.6 // xnu-3248.60.10/bsd/kern/kern_descrip.c getdtablesize(). For Linux glibc, // see glibc-2.24/sysdeps/posix/sysconf.c __sysconf() and - // glibc-2.24/sysdeps/posix/getdtsz.c __getdtablesize(). + // glibc-2.24/sysdeps/posix/getdtsz.c __getdtablesize(). For Android, see + // 7.0.0 bionic/libc/bionic/sysconf.cpp sysconf() and + // bionic/libc/bionic/ndk_cruft.cpp getdtablesize(). int max_fd = implicit_cast(sysconf(_SC_OPEN_MAX)); + +#if !defined(OS_ANDROID) + // getdtablesize() was removed effective Android 5.0.0 (API 21). Since it + // returns the same thing as the sysconf() above, just skip it. See + // https://android.googlesource.com/platform/bionic/+/462abab12b074c62c0999859e65d5a32ebb41951. max_fd = std::max(max_fd, getdtablesize()); +#endif #if !defined(OS_LINUX) || defined(OPEN_MAX) // Linux does not provide OPEN_MAX. See @@ -198,7 +206,7 @@ void CloseMultipleNowOrOnExec(int fd, int preserve_fd) { } else { PLOG(WARNING) << "sysctl"; } -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_ANDROID) // See linux-4.4.27/fs/file.c sysctl_nr_open, referenced by kernel/sys.c // do_prlimit() and kernel/sysctl.c fs_table. Inability to open this file is // not considered an error, because /proc may not be available or usable. diff --git a/util/posix/drop_privileges.cc b/util/posix/drop_privileges.cc index 3fb0ab4a..5c809904 100644 --- a/util/posix/drop_privileges.cc +++ b/util/posix/drop_privileges.cc @@ -71,7 +71,7 @@ void DropPrivileges() { CHECK_EQ(setegid(egid), -1); } } -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_ANDROID) PCHECK(setresgid(gid, gid, gid) == 0) << "setresgid"; PCHECK(setresuid(uid, uid, uid) == 0) << "setresuid"; diff --git a/util/posix/symbolic_constants_posix.cc b/util/posix/symbolic_constants_posix.cc index c952e82a..4ea2300b 100644 --- a/util/posix/symbolic_constants_posix.cc +++ b/util/posix/symbolic_constants_posix.cc @@ -14,9 +14,9 @@ #include "util/posix/symbolic_constants_posix.h" +#include #include #include -#include #include "base/macros.h" #include "base/strings/stringprintf.h" @@ -64,7 +64,7 @@ const char* kSignalNames[] = { "INFO", "USR1", "USR2", -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_ANDROID) // sed -Ene 's/^#define[[:space:]]SIG([[:alnum:]]+)[[:space:]]+[[:digit:]]{1,2}([[:space:]]|$).*/ "\1",/p' // /usr/include/asm-generic/signal.h // and fix up by removing SIGIOT, SIGLOST, SIGUNUSED, and SIGRTMIN. @@ -101,7 +101,7 @@ const char* kSignalNames[] = { "SYS", #endif }; -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_ANDROID) // NSIG is 64 to account for real-time signals. static_assert(arraysize(kSignalNames) == 32, "kSignalNames length"); #else diff --git a/util/posix/symbolic_constants_posix_test.cc b/util/posix/symbolic_constants_posix_test.cc index 72e37bd4..6779a30d 100644 --- a/util/posix/symbolic_constants_posix_test.cc +++ b/util/posix/symbolic_constants_posix_test.cc @@ -65,7 +65,7 @@ const struct { #if defined(OS_MACOSX) {SIGEMT, "SIGEMT", "EMT"}, {SIGINFO, "SIGINFO", "INFO"}, -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_ANDROID) {SIGPWR, "SIGPWR", "PWR"}, {SIGSTKFLT, "SIGSTKFLT", "STKFLT"}, #endif @@ -120,7 +120,7 @@ TEST(SymbolicConstantsPOSIX, SignalToString) { kSignalTestData[index].short_name); } -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_ANDROID) // NSIG is 64 to account for real-time signals. const int kSignalCount = 32; #else