author | James Willcox <snorp@snorp.net> |
Mon, 23 Apr 2018 11:58:31 -0500 | |
changeset 415337 | 6bf69d965bbe697e69fc0df014e7f326aa423385 |
parent 415336 | 5336e6fd895be772cf603dbd8a6580be723829aa |
child 415338 | 31dd07dd000efefc62ae97317ac336aec085ef79 |
push id | 102559 |
push user | jwillcox@mozilla.com |
push date | Tue, 24 Apr 2018 19:22:41 +0000 |
treeherder | mozilla-inbound@6bf69d965bbe [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ted |
bugs | 1456203, 699213 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h | file | annotate | diff | comparison | revisions |
--- a/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h +++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h @@ -138,16 +138,39 @@ extern "C" { # pragma push_macro("stat64") # pragma push_macro("fstat64") # pragma push_macro("lstat64") # undef stat64 # undef fstat64 # undef lstat64 #endif +#if defined(__ANDROID__) && defined(__x86_64__) +// A number of x86_64 syscalls are blocked by seccomp on recent Android; +// undefine them so that modern alternatives will be used instead where +// possible. +// The alternative syscalls have been sanity checked against linux-3.4+; +// older versions might not work. +# undef __NR_getdents +# undef __NR_dup2 +# undef __NR_fork +# undef __NR_getpgrp +# undef __NR_open +# undef __NR_poll +# undef __NR_readlink +# undef __NR_stat +# undef __NR_unlink +# undef __NR_pipe +#endif + +#if defined(__ANDROID__) +// waitpid is blocked by seccomp on all architectures on recent Android. +# undef __NR_waitpid +#endif + /* As glibc often provides subtly incompatible data structures (and implicit * wrapper functions that convert them), we provide our own kernel data * structures for use by the system calls. * These structures have been developed by using Linux 2.6.23 headers for * reference. Note though, we do not care about exact API compatibility * with the kernel, and in fact the kernel often does not have a single * API that works across architectures. Instead, we try to mimic the glibc * API where reasonable, and only guarantee ABI compatibility with the @@ -177,18 +200,18 @@ struct kernel_dirent64 { unsigned long long d_ino; long long d_off; unsigned short d_reclen; unsigned char d_type; char d_name[256]; }; /* include/linux/dirent.h */ -#if defined(__aarch64__) -// aarch64 only defines dirent64, just uses that for dirent too. +#if !defined(__NR_getdents) +// when getdents is not available, getdents64 is used for both. #define kernel_dirent kernel_dirent64 #else struct kernel_dirent { long d_ino; long d_off; unsigned short d_reclen; char d_name[256]; }; @@ -1064,16 +1087,17 @@ struct kernel_statfs { #endif #ifndef __NR_quotactl #define __NR_quotactl 60 #endif #ifndef __NR_getdents64 #define __NR_getdents64 61 #endif #ifndef __NR_getdents +// when getdents is not available, getdents64 is used for both. #define __NR_getdents __NR_getdents64 #endif #ifndef __NR_pread64 #define __NR_pread64 67 #endif #ifndef __NR_pwrite64 #define __NR_pwrite64 68 #endif @@ -1172,16 +1196,20 @@ struct kernel_statfs { #endif #ifndef __NR_sched_setaffinity #define __NR_sched_setaffinity 203 #define __NR_sched_getaffinity 204 #endif #ifndef __NR_getdents64 #define __NR_getdents64 217 #endif +#ifndef __NR_getdents +// when getdents is not available, getdents64 is used for both. +#define __NR_getdents __NR_getdents64 +#endif #ifndef __NR_set_tid_address #define __NR_set_tid_address 218 #endif #ifndef __NR_fadvise64 #define __NR_fadvise64 221 #endif #ifndef __NR_clock_gettime #define __NR_clock_gettime 228 @@ -3331,29 +3359,32 @@ struct kernel_statfs { LSS_INLINE _syscall1(void *, brk, void *, e) LSS_INLINE _syscall1(int, chdir, const char *,p) LSS_INLINE _syscall1(int, close, int, f) LSS_INLINE _syscall2(int, clock_getres, int, c, struct kernel_timespec*, t) LSS_INLINE _syscall2(int, clock_gettime, int, c, struct kernel_timespec*, t) LSS_INLINE _syscall1(int, dup, int, f) - #if !defined(__aarch64__) - // The dup2 syscall has been deprecated on aarch64. We polyfill it below. + #if defined(__NR_dup2) + // dup2 is polyfilled below when not available. LSS_INLINE _syscall2(int, dup2, int, s, int, d) #endif + #if defined(__NR_dup3) + LSS_INLINE _syscall3(int, dup3, int, s, int, d, int, f) + #endif LSS_INLINE _syscall3(int, execve, const char*, f, const char*const*,a,const char*const*, e) LSS_INLINE _syscall1(int, _exit, int, e) LSS_INLINE _syscall1(int, exit_group, int, e) LSS_INLINE _syscall3(int, fcntl, int, f, int, c, long, a) - #if !defined(__aarch64__) - // The fork syscall has been deprecated on aarch64. We polyfill it below. + #if defined(__NR_fork) + // fork is polyfilled below when not available. LSS_INLINE _syscall0(pid_t, fork) #endif LSS_INLINE _syscall2(int, fstat, int, f, struct kernel_stat*, b) LSS_INLINE _syscall2(int, fstatfs, int, f, struct kernel_statfs*, b) #if defined(__x86_64__) /* Need to make sure off_t isn't truncated to 32-bits under x32. */ @@ -3368,18 +3399,17 @@ struct kernel_statfs { int, o, int, v, struct kernel_timespec*, t) LSS_INLINE _syscall3(int, getdents, int, f, struct kernel_dirent*, d, int, c) LSS_INLINE _syscall3(int, getdents64, int, f, struct kernel_dirent64*, d, int, c) LSS_INLINE _syscall0(gid_t, getegid) LSS_INLINE _syscall0(uid_t, geteuid) - #if !defined(__aarch64__) - // The getgprp syscall has been deprecated on aarch64. + #if defined(__NR_getpgrp) LSS_INLINE _syscall0(pid_t, getpgrp) #endif LSS_INLINE _syscall0(pid_t, getpid) LSS_INLINE _syscall0(pid_t, getppid) LSS_INLINE _syscall2(int, getpriority, int, a, int, b) LSS_INLINE _syscall3(int, getresgid, gid_t *, r, gid_t *, e, gid_t *, s) @@ -3430,43 +3460,54 @@ struct kernel_statfs { LSS_INLINE _syscall6(long, move_pages, pid_t, p, unsigned long, n, void **,g, int *, d, int *, s, int, f) LSS_INLINE _syscall3(int, mprotect, const void *,a, size_t, l, int, p) LSS_INLINE _syscall5(void*, _mremap, void*, o, size_t, os, size_t, ns, unsigned long, f, void *, a) - #if !defined(__aarch64__) - // The open and poll syscalls have been deprecated on aarch64. We polyfill - // them below. + #if defined(__NR_open) + // open is polyfilled below when not available. LSS_INLINE _syscall3(int, open, const char*, p, int, f, int, m) + #endif + #if defined(__NR_poll) + // poll is polyfilled below when not available. LSS_INLINE _syscall3(int, poll, struct kernel_pollfd*, u, unsigned int, n, int, t) #endif + #if defined(__NR_ppoll) + LSS_INLINE _syscall5(int, ppoll, struct kernel_pollfd *, u, + unsigned int, n, const struct kernel_timespec *, t, + const struct kernel_sigset_t *, sigmask, size_t, s) + #endif LSS_INLINE _syscall5(int, prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5) LSS_INLINE _syscall4(long, ptrace, int, r, pid_t, p, void *, a, void *, d) #if defined(__NR_quotactl) // Defined on x86_64 / i386 only LSS_INLINE _syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr) #endif LSS_INLINE _syscall3(ssize_t, read, int, f, void *, b, size_t, c) - #if !defined(__aarch64__) - // The readlink syscall has been deprecated on aarch64. We polyfill below. + #if defined(__NR_readlink) + // readlink is polyfilled below when not available. LSS_INLINE _syscall3(int, readlink, const char*, p, char*, b, size_t, s) #endif + #if defined(__NR_readlinkat) + LSS_INLINE _syscall4(int, readlinkat, int, d, const char *, p, char *, b, + size_t, s) + #endif LSS_INLINE _syscall4(int, rt_sigaction, int, s, const struct kernel_sigaction*, a, struct kernel_sigaction*, o, size_t, c) LSS_INLINE _syscall2(int, rt_sigpending, struct kernel_sigset_t *, s, size_t, c) LSS_INLINE _syscall4(int, rt_sigprocmask, int, h, const struct kernel_sigset_t*, s, struct kernel_sigset_t*, o, size_t, c) @@ -3493,29 +3534,29 @@ struct kernel_statfs { LSS_INLINE _syscall2(int, setrlimit, int, r, const struct kernel_rlimit*, l) LSS_INLINE _syscall0(pid_t, setsid) LSS_INLINE _syscall2(int, sigaltstack, const stack_t*, s, const stack_t*, o) #if defined(__NR_sigreturn) LSS_INLINE _syscall1(int, sigreturn, unsigned long, u) #endif - #if !defined(__aarch64__) - // The stat syscall has been deprecated on aarch64. We polyfill it below. + #if defined(__NR_stat) + // stat is polyfilled below when not available. LSS_INLINE _syscall2(int, stat, const char*, f, struct kernel_stat*, b) #endif LSS_INLINE _syscall2(int, statfs, const char*, f, struct kernel_statfs*, b) LSS_INLINE _syscall3(int, tgkill, pid_t, p, pid_t, t, int, s) LSS_INLINE _syscall2(int, tkill, pid_t, p, int, s) - #if !defined(__aarch64__) - // The unlink syscall has been deprecated on aarch64. We polyfill it below. + #if defined(__NR_unlink) + // unlink is polyfilled below when not available. LSS_INLINE _syscall1(int, unlink, const char*, f) #endif LSS_INLINE _syscall3(ssize_t, write, int, f, const void *, b, size_t, c) LSS_INLINE _syscall3(ssize_t, writev, int, f, const struct kernel_iovec*, v, size_t, c) #if defined(__NR_getcpu) LSS_INLINE _syscall3(long, getcpu, unsigned *, cpu, @@ -3603,31 +3644,33 @@ struct kernel_statfs { union { loff_t off; unsigned w[2]; } o = { offset }, l = { len }; return LSS_NAME(_fallocate)(fd, mode, o.w[0], o.w[1], l.w[0], l.w[1]); } #else LSS_INLINE _syscall4(int, fallocate, int, f, int, mode, loff_t, offset, loff_t, len) #endif #endif + #if defined(__NR_newfstatat) + LSS_INLINE _syscall4(int, newfstatat, int, d, + const char *, p, + struct kernel_stat*, b, int, f) + #endif #if defined(__x86_64__) || defined(__s390x__) LSS_INLINE int LSS_NAME(getresgid32)(gid_t *rgid, gid_t *egid, gid_t *sgid) { return LSS_NAME(getresgid)(rgid, egid, sgid); } LSS_INLINE int LSS_NAME(getresuid32)(uid_t *ruid, uid_t *euid, uid_t *suid) { return LSS_NAME(getresuid)(ruid, euid, suid); } - LSS_INLINE _syscall4(int, newfstatat, int, d, - const char *, p, - struct kernel_stat*, b, int, f) LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) { return LSS_NAME(setfsgid)(gid); } LSS_INLINE int LSS_NAME(setfsuid32)(uid_t uid) { return LSS_NAME(setfsuid)(uid); } @@ -3670,27 +3713,20 @@ struct kernel_statfs { struct kernel_sigset_t *oldset) { return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); } LSS_INLINE int LSS_NAME(sigsuspend)(const struct kernel_sigset_t *set) { return LSS_NAME(rt_sigsuspend)(set, (KERNEL_NSIG+7)/8); } #endif - #if defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ - defined(__ARM_EABI__) || defined(__aarch64__) || \ - (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) || \ - defined(__s390__) + #if defined(__NR_wait4) LSS_INLINE _syscall4(pid_t, wait4, pid_t, p, int*, s, int, o, struct kernel_rusage*, r) - - LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options){ - return LSS_NAME(wait4)(pid, status, options, 0); - } #endif #if defined(__NR_openat) LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m) #endif #if defined(__NR_unlinkat) LSS_INLINE _syscall3(int, unlinkat, int, d, const char *, p, int, f) #endif #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \ @@ -4186,18 +4222,18 @@ struct kernel_statfs { return LSS_NAME(socketcall)(8, d, type, protocol, sv); } #endif #if defined(__NR_fstatat64) LSS_INLINE _syscall4(int, fstatat64, int, d, const char *, p, struct kernel_stat64 *, b, int, f) #endif - #if defined(__i386__) || defined(__PPC__) || \ - (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) + #if defined(__NR_waitpid) + // waitpid is polyfilled below when not available. LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p, int*, s, int, o) #endif #if defined(__mips__) /* sys_pipe() on MIPS has non-standard calling conventions, as it returns * both file handles through CPU registers. */ LSS_INLINE int LSS_NAME(pipe)(int *p) { @@ -4214,20 +4250,23 @@ struct kernel_statfs { LSS_ERRNO = __errnovalue; return -1; } else { p[0] = __v0; p[1] = __v1; return 0; } } - #elif !defined(__aarch64__) - // The unlink syscall has been deprecated on aarch64. We polyfill it below. + #elif defined(__NR_pipe) + // pipe is polyfilled below when not available. LSS_INLINE _syscall1(int, pipe, int *, p) #endif + #if defined(__NR_pipe2) + LSS_INLINE _syscall2(int, pipe2, int *, pipefd, int, flags) + #endif /* TODO(csilvers): see if ppc can/should support this as well */ #if defined(__i386__) || defined(__ARM_ARCH_3__) || \ defined(__ARM_EABI__) || \ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) || \ (defined(__s390__) && !defined(__s390x__)) #define __NR__statfs64 __NR_statfs64 #define __NR__fstatfs64 __NR_fstatfs64 LSS_INLINE _syscall3(int, _statfs64, const char*, p, @@ -4394,72 +4433,84 @@ struct kernel_statfs { } LSS_INLINE int LSS_NAME(readahead)(int fd, loff_t off, int len) { union { loff_t off; unsigned arg[2]; } o = { off }; return LSS_NAME(_readahead)(fd, LSS_LLARG_PAD o.arg[0], o.arg[1], len); } #endif #endif -#if defined(__aarch64__) - LSS_INLINE _syscall3(int, dup3, int, s, int, d, int, f) - LSS_INLINE _syscall4(int, newfstatat, int, dirfd, const char *, pathname, - struct kernel_stat *, buf, int, flags) - LSS_INLINE _syscall2(int, pipe2, int *, pipefd, int, flags) - LSS_INLINE _syscall5(int, ppoll, struct kernel_pollfd *, u, - unsigned int, n, const struct kernel_timespec *, t, - const struct kernel_sigset_t *, sigmask, size_t, s) - LSS_INLINE _syscall4(int, readlinkat, int, d, const char *, p, char *, b, - size_t, s) -#endif - /* * Polyfills for deprecated syscalls. */ -#if defined(__aarch64__) +#if !defined(__NR_dup2) LSS_INLINE int LSS_NAME(dup2)(int s, int d) { return LSS_NAME(dup3)(s, d, 0); } +#endif +#if !defined(__NR_open) LSS_INLINE int LSS_NAME(open)(const char *pathname, int flags, int mode) { return LSS_NAME(openat)(AT_FDCWD, pathname, flags, mode); } +#endif +#if !defined(__NR_unlink) LSS_INLINE int LSS_NAME(unlink)(const char *pathname) { return LSS_NAME(unlinkat)(AT_FDCWD, pathname, 0); } +#endif +#if !defined(__NR_readlink) LSS_INLINE int LSS_NAME(readlink)(const char *pathname, char *buffer, size_t size) { return LSS_NAME(readlinkat)(AT_FDCWD, pathname, buffer, size); } +#endif +#if !defined(__NR_pipe) LSS_INLINE pid_t LSS_NAME(pipe)(int *pipefd) { return LSS_NAME(pipe2)(pipefd, 0); } +#endif +#if !defined(__NR_poll) LSS_INLINE int LSS_NAME(poll)(struct kernel_pollfd *fds, unsigned int nfds, int timeout) { struct kernel_timespec timeout_ts; struct kernel_timespec *timeout_ts_p = NULL; if (timeout >= 0) { timeout_ts.tv_sec = timeout / 1000; timeout_ts.tv_nsec = (timeout % 1000) * 1000000; timeout_ts_p = &timeout_ts; } return LSS_NAME(ppoll)(fds, nfds, timeout_ts_p, NULL, 0); } +#endif +#if !defined(__NR_stat) LSS_INLINE int LSS_NAME(stat)(const char *pathname, struct kernel_stat *buf) { return LSS_NAME(newfstatat)(AT_FDCWD, pathname, buf, 0); } +#endif +#if !defined(__NR_waitpid) + LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options) { + return LSS_NAME(wait4)(pid, status, options, 0); + } +#endif + +#if !defined(__NR_fork) +// TODO: define this in an arch-independant way instead of inlining the clone +// syscall body. + +# if defined(__aarch64__) LSS_INLINE pid_t LSS_NAME(fork)(void) { // No fork syscall on aarch64 - implement by means of the clone syscall. // Note that this does not reset glibc's cached view of the PID/TID, so // some glibc interfaces might go wrong in the forked subprocess. int flags = SIGCHLD; void *child_stack = NULL; void *parent_tidptr = NULL; void *newtls = NULL; @@ -4468,16 +4519,33 @@ struct kernel_statfs { LSS_REG(0, flags); LSS_REG(1, child_stack); LSS_REG(2, parent_tidptr); LSS_REG(3, newtls); LSS_REG(4, child_tidptr); LSS_BODY(pid_t, clone, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), "r"(__r4)); } +# elif defined(__x86_64__) + LSS_INLINE pid_t LSS_NAME(fork)(void) { + // Android disallows the fork syscall on x86_64 - implement by means of the + // clone syscall as above for aarch64. + int flags = SIGCHLD; + void *child_stack = NULL; + void *parent_tidptr = NULL; + void *newtls = NULL; + void *child_tidptr = NULL; + + LSS_BODY(5, pid_t, clone, LSS_SYSCALL_ARG(flags), + LSS_SYSCALL_ARG(child_stack), LSS_SYSCALL_ARG(parent_tidptr), + LSS_SYSCALL_ARG(newtls), LSS_SYSCALL_ARG(child_tidptr)); + } +# else +# error missing fork polyfill for this architecture +# endif #endif #ifdef __ANDROID__ /* These restore the original values of these macros saved by the * corresponding #pragma push_macro near the top of this file. */ # pragma pop_macro("stat64") # pragma pop_macro("fstat64") # pragma pop_macro("lstat64")