Port the util library to Android

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 <rsesek@chromium.org>
This commit is contained in:
Mark Mentovai 2016-10-31 11:23:00 -04:00
parent f735d050c4
commit e956a8252f
6 changed files with 30 additions and 12 deletions

View File

@ -73,9 +73,19 @@ bool WeakFileHandleFileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
iovec* iov = reinterpret_cast<iovec*>(&(*iovecs)[0]); iovec* iov = reinterpret_cast<iovec*>(&(*iovecs)[0]);
size_t remaining_iovecs = iovecs->size(); 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 <limits.h>, 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) { while (size > 0) {
size_t writev_iovec_count = size_t writev_iovec_count = std::min(remaining_iovecs, kIovMax);
std::min(remaining_iovecs, implicit_cast<size_t>(IOV_MAX));
ssize_t written = ssize_t written =
HANDLE_EINTR(writev(file_handle_, iov, writev_iovec_count)); HANDLE_EINTR(writev(file_handle_, iov, writev_iovec_count));
if (written < 0) { if (written < 0) {

View File

@ -111,7 +111,7 @@ bool UUID::InitializeWithNew() {
} }
InitializeFromSystemUUID(&system_uuid); InitializeFromSystemUUID(&system_uuid);
return true; 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 // Linux does not provide a UUID generator in a widely-available system
// library. uuid_generate() from libuuid is not available everywhere. // library. uuid_generate() from libuuid is not available everywhere.
base::RandBytes(this, sizeof(*this)); base::RandBytes(this, sizeof(*this));

View File

@ -88,7 +88,7 @@ using ScopedDIR = std::unique_ptr<DIR, ScopedDIRCloser>;
bool CloseMultipleNowOrOnExecUsingFDDir(int fd, int preserve_fd) { bool CloseMultipleNowOrOnExecUsingFDDir(int fd, int preserve_fd) {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
const char kFDDir[] = "/dev/fd"; const char kFDDir[] = "/dev/fd";
#elif defined(OS_LINUX) #elif defined(OS_LINUX) || defined(OS_ANDROID)
const char kFDDir[] = "/proc/self/fd"; const char kFDDir[] = "/proc/self/fd";
#endif #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 // 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, // xnu-3248.60.10/bsd/kern/kern_descrip.c getdtablesize(). For Linux glibc,
// see glibc-2.24/sysdeps/posix/sysconf.c __sysconf() and // 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<int>(sysconf(_SC_OPEN_MAX)); int max_fd = implicit_cast<int>(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()); max_fd = std::max(max_fd, getdtablesize());
#endif
#if !defined(OS_LINUX) || defined(OPEN_MAX) #if !defined(OS_LINUX) || defined(OPEN_MAX)
// Linux does not provide OPEN_MAX. See // Linux does not provide OPEN_MAX. See
@ -198,7 +206,7 @@ void CloseMultipleNowOrOnExec(int fd, int preserve_fd) {
} else { } else {
PLOG(WARNING) << "sysctl"; 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 // 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 // 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. // not considered an error, because /proc may not be available or usable.

View File

@ -71,7 +71,7 @@ void DropPrivileges() {
CHECK_EQ(setegid(egid), -1); CHECK_EQ(setegid(egid), -1);
} }
} }
#elif defined(OS_LINUX) #elif defined(OS_LINUX) || defined(OS_ANDROID)
PCHECK(setresgid(gid, gid, gid) == 0) << "setresgid"; PCHECK(setresgid(gid, gid, gid) == 0) << "setresgid";
PCHECK(setresuid(uid, uid, uid) == 0) << "setresuid"; PCHECK(setresuid(uid, uid, uid) == 0) << "setresuid";

View File

@ -14,9 +14,9 @@
#include "util/posix/symbolic_constants_posix.h" #include "util/posix/symbolic_constants_posix.h"
#include <signal.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/signal.h>
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
@ -64,7 +64,7 @@ const char* kSignalNames[] = {
"INFO", "INFO",
"USR1", "USR1",
"USR2", "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' // sed -Ene 's/^#define[[:space:]]SIG([[:alnum:]]+)[[:space:]]+[[:digit:]]{1,2}([[:space:]]|$).*/ "\1",/p'
// /usr/include/asm-generic/signal.h // /usr/include/asm-generic/signal.h
// and fix up by removing SIGIOT, SIGLOST, SIGUNUSED, and SIGRTMIN. // and fix up by removing SIGIOT, SIGLOST, SIGUNUSED, and SIGRTMIN.
@ -101,7 +101,7 @@ const char* kSignalNames[] = {
"SYS", "SYS",
#endif #endif
}; };
#if defined(OS_LINUX) #if defined(OS_LINUX) || defined(OS_ANDROID)
// NSIG is 64 to account for real-time signals. // NSIG is 64 to account for real-time signals.
static_assert(arraysize(kSignalNames) == 32, "kSignalNames length"); static_assert(arraysize(kSignalNames) == 32, "kSignalNames length");
#else #else

View File

@ -65,7 +65,7 @@ const struct {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
{SIGEMT, "SIGEMT", "EMT"}, {SIGEMT, "SIGEMT", "EMT"},
{SIGINFO, "SIGINFO", "INFO"}, {SIGINFO, "SIGINFO", "INFO"},
#elif defined(OS_LINUX) #elif defined(OS_LINUX) || defined(OS_ANDROID)
{SIGPWR, "SIGPWR", "PWR"}, {SIGPWR, "SIGPWR", "PWR"},
{SIGSTKFLT, "SIGSTKFLT", "STKFLT"}, {SIGSTKFLT, "SIGSTKFLT", "STKFLT"},
#endif #endif
@ -120,7 +120,7 @@ TEST(SymbolicConstantsPOSIX, SignalToString) {
kSignalTestData[index].short_name); kSignalTestData[index].short_name);
} }
#if defined(OS_LINUX) #if defined(OS_LINUX) || defined(OS_ANDROID)
// NSIG is 64 to account for real-time signals. // NSIG is 64 to account for real-time signals.
const int kSignalCount = 32; const int kSignalCount = 32;
#else #else