bug 595167 - Make Breakpad client libs work on Android. r=mwu a=blocking-fennec
authorTed Mielczarek <ted.mielczarek@gmail.com>
Wed, 13 Oct 2010 11:37:58 -0400
changeset 56278 ca8226c47fea226ec94cb5755a537c505bebc0d0
parent 56275 4c7a7fd3dc8e0f27f258b38917cd5c1a2d63e40d
child 56279 1f000e6c5237dffab00563f64ea75456af6cbb5a
push idunknown
push userunknown
push dateunknown
reviewersmwu, blocking-fennec
bugs595167
milestone2.0b8pre
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
bug 595167 - Make Breakpad client libs work on Android. r=mwu a=blocking-fennec
toolkit/crashreporter/google-breakpad/src/client/linux/android_link.h
toolkit/crashreporter/google-breakpad/src/client/linux/android_ucontext.h
toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc
toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc
toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in
toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc
toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/android_link.h
@@ -0,0 +1,4 @@
+#include <sys/exec_elf.h>
+#define ElfW(type)	_ElfW (Elf, ELFSIZE, type)
+#define _ElfW(e,w,t)	_ElfW_1 (e, w, _##t)
+#define _ElfW_1(e,w,t)	e##w##t
new file mode 100644
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/android_ucontext.h
@@ -0,0 +1,46 @@
+#ifndef GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
+#define GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
+
+#include <signal.h>
+
+// Adapted from platform-linux.cc in V8
+#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
+// Android runs a fairly new Linux kernel, so signal info is there,
+// but the C library doesn't have the structs defined.
+
+struct sigcontext {
+  uint32_t trap_no;
+  uint32_t error_code;
+  uint32_t oldmask;
+  uint32_t arm_r0;
+  uint32_t arm_r1;
+  uint32_t arm_r2;
+  uint32_t arm_r3;
+  uint32_t arm_r4;
+  uint32_t arm_r5;
+  uint32_t arm_r6;
+  uint32_t arm_r7;
+  uint32_t arm_r8;
+  uint32_t arm_r9;
+  uint32_t arm_r10;
+  uint32_t arm_fp;
+  uint32_t arm_ip;
+  uint32_t arm_sp;
+  uint32_t arm_lr;
+  uint32_t arm_pc;
+  uint32_t arm_cpsr;
+  uint32_t fault_address;
+};
+typedef uint32_t __sigset_t;
+typedef struct sigcontext mcontext_t;
+typedef struct ucontext {
+  uint32_t uc_flags;
+  struct ucontext* uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  __sigset_t uc_sigmask;
+} ucontext_t;
+
+#endif
+
+#endif  // GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc
@@ -68,22 +68,28 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/limits.h>
 #include <sched.h>
 #include <signal.h>
 #include <stdio.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
+#if !defined(__ANDROID__)
 #include <sys/signal.h>
+#endif
 #include <sys/syscall.h>
+#if !defined(__ANDROID__)
 #include <sys/ucontext.h>
 #include <sys/user.h>
+#endif
 #include <sys/wait.h>
+#if !defined(__ANDROID__)
 #include <ucontext.h>
+#endif
 #include <unistd.h>
 
 #include <algorithm>
 #include <vector>
 
 #include "common/linux/linux_libc_support.h"
 #include "common/linux/linux_syscall_support.h"
 #include "common/memory.h"
@@ -181,17 +187,17 @@ bool ExceptionHandler::InstallHandlers()
   static const unsigned kSigStackSize = 8192;
 
   signal_stack = malloc(kSigStackSize);
   stack_t stack;
   memset(&stack, 0, sizeof(stack));
   stack.ss_sp = signal_stack;
   stack.ss_size = kSigStackSize;
 
-  if (sigaltstack(&stack, NULL) == -1)
+  if (sys_sigaltstack(&stack, NULL) == -1)
     return false;
 
   struct sigaction sa;
   memset(&sa, 0, sizeof(sa));
   sigemptyset(&sa.sa_mask);
 
   // mask all exception signals when we're handling one of them.
   for (unsigned i = 0; kExceptionSignals[i] != -1; ++i)
@@ -305,17 +311,17 @@ int ExceptionHandler::ThreadEntry(void *
 
 // This function runs in a compromised context: see the top of the file.
 // Runs on the crashing thread.
 bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
   if (filter_ && !filter_(callback_context_))
     return false;
 
   // Allow ourselves to be dumped.
-  prctl(PR_SET_DUMPABLE, 1);
+  sys_prctl(PR_SET_DUMPABLE, 1);
   CrashContext context;
   memcpy(&context.siginfo, info, sizeof(siginfo_t));
   memcpy(&context.context, uc, sizeof(struct ucontext));
 #if !defined(__ARM_EABI__)
   // FP state is not part of user ABI on ARM Linux.
   struct ucontext *uc_ptr = (struct ucontext*)uc;
   if (uc_ptr->uc_mcontext.fpregs) {
     memcpy(&context.float_state,
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
@@ -28,19 +28,21 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
 #define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
 
 #include <vector>
 #include <string>
 
+#include <pthread.h>
 #include <signal.h>
 #include <stdio.h>
 
+#include "client/linux/android_ucontext.h"
 #include "client/linux/crash_generation/crash_generation_client.h"
 #include "processor/scoped_ptr.h"
 
 struct sigaction;
 
 namespace google_breakpad {
 
 class ExceptionHandler;
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc
@@ -40,17 +40,19 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 #include <unistd.h>
 #include <elf.h>
 #include <errno.h>
 #include <fcntl.h>
+#if !defined(__ANDROID__)
 #include <link.h>
+#endif
 
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 
 #include <algorithm>
 
 #include "client/linux/minidump_writer/directory_reader.h"
@@ -112,21 +114,26 @@ inline bool IsMappedFileOpenUnsafe(
   return my_strncmp(mapping->name,
                     kMappedFileUnsafePrefix,
                     sizeof(kMappedFileUnsafePrefix) - 1) == 0;
 }
 
 bool GetThreadRegisters(ThreadInfo* info) {
   pid_t tid = info->tid;
 
-  if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1 ||
-      sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) {
+  if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1) {
     return false;
   }
 
+#if !defined(__ANDROID__)
+  if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) {
+    return false;
+  }
+#endif
+
 #if defined(__i386)
   if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1)
     return false;
 #endif
 
 #if defined(__i386) || defined(__x86_64)
   for (unsigned i = 0; i < ThreadInfo::kNumDebugRegisters; ++i) {
     if (sys_ptrace(
@@ -420,17 +427,17 @@ bool LinuxDumper::ThreadInfoGet(ThreadIn
       return false;
 
   const uint8_t* stack_pointer;
 #if defined(__i386)
   memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
 #elif defined(__x86_64)
   memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
 #elif defined(__ARM_EABI__)
-  memcpy(&stack_pointer, &info->regs.uregs[R13], sizeof(info->regs.uregs[R13]));
+  memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
 #else
 #error "This code hasn't been ported to your platform yet."
 #endif
 
   if (!GetStackInfo(&info->stack, &info->stack_len,
                     (uintptr_t) stack_pointer))
     return false;
 
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h
@@ -29,28 +29,48 @@
 
 #ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
 #define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
 
 #include <elf.h>
 #include <linux/limits.h>
 #include <stdint.h>
 #include <sys/types.h>
+#if !defined(__ANDROID__)
 #include <sys/user.h>
+#endif
 
 #include "common/memory.h"
 #include "google_breakpad/common/minidump_format.h"
 
 namespace google_breakpad {
 
+#if defined(__i386) || defined(__x86_64)
 typedef typeof(((struct user*) 0)->u_debugreg[0]) debugreg_t;
+#endif
 
 // Typedef for our parsing of the auxv variables in /proc/pid/auxv.
 #if defined(__i386) || defined(__ARM_EABI__)
+#if !defined(__ANDROID__)
 typedef Elf32_auxv_t elf_aux_entry;
+#else
+// Android is missing this structure definition
+typedef struct
+{
+  uint32_t a_type;              /* Entry type */
+  union
+    {
+      uint32_t a_val;           /* Integer value */
+    } a_un;
+} elf_aux_entry;
+
+#if !defined(AT_SYSINFO_EHDR)
+#define AT_SYSINFO_EHDR 33
+#endif
+#endif  // __ANDROID__
 #elif defined(__x86_64__)
 typedef Elf64_auxv_t elf_aux_entry;
 #endif
 // When we find the VDSO mapping in the process's address space, this
 // is the name we use for it when writing it to the minidump.
 // This should always be less than NAME_MAX!
 const char kLinuxGateLibraryName[] = "linux-gate.so";
 
@@ -72,18 +92,22 @@ struct ThreadInfo {
   static const unsigned kNumDebugRegisters = 8;
   debugreg_t dregs[8];
 #if defined(__i386)
   user_fpxregs_struct fpxregs;
 #endif  // defined(__i386)
 
 #elif defined(__ARM_EABI__)
   // Mimicking how strace does this(see syscall.c, search for GETREGS)
+#if defined(__ANDROID__)
+  struct pt_regs regs;
+#else
   struct user_regs regs;
   struct user_fpregs fpregs;
+#endif  // __ANDROID__
 #endif
 };
 
 // One of these is produced for each mapping in the process (i.e. line in
 // /proc/$x/maps).
 struct MappingInfo {
   uintptr_t start_addr;
   size_t size;
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc
@@ -45,28 +45,35 @@
 
 #include "client/linux/minidump_writer/minidump_writer.h"
 #include "client/minidump_file_writer-inl.h"
 
 #include <algorithm>
 
 #include <errno.h>
 #include <fcntl.h>
+#if defined(__ANDROID__)
+#include "client/linux/android_link.h"
+#else
 #include <link.h>
+#endif
 #include <stdio.h>
 #include <unistd.h>
+#if !defined(__ANDROID__)
 #include <sys/ucontext.h>
 #include <sys/user.h>
+#endif
 #include <sys/utsname.h>
 
 #include "client/minidump_file_writer.h"
 #include "google_breakpad/common/minidump_format.h"
 #include "google_breakpad/common/minidump_cpu_amd64.h"
 #include "google_breakpad/common/minidump_cpu_x86.h"
 
+#include "client/linux/android_ucontext.h"
 #include "client/linux/handler/exception_handler.h"
 #include "client/linux/minidump_writer/line_reader.h"
 #include "client/linux/minidump_writer/linux_dumper.h"
 #include "client/linux/minidump_writer/minidump_extension_linux.h"
 #include "common/linux/linux_libc_support.h"
 #include "common/linux/linux_syscall_support.h"
 
 using google_breakpad::ThreadInfo;
@@ -332,21 +339,23 @@ typedef MDRawContextARM RawContextCPU;
 static void CPUFillFromThreadInfo(MDRawContextARM *out,
                                   const ThreadInfo &info) {
   out->context_flags = MD_CONTEXT_ARM_FULL;
 
   for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i)
     out->iregs[i] = info.regs.uregs[i];
   // No CPSR register in ThreadInfo(it's not accessible via ptrace)
   out->cpsr = 0;
+#if !defined(__ANDROID__)
   out->float_save.fpscr = info.fpregs.fpsr |
     (static_cast<u_int64_t>(info.fpregs.fpcr) << 32);
   //TODO: sort this out, actually collect floating point registers
   memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
   memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
+#endif
 }
 
 static void CPUFillFromUContext(MDRawContextARM *out, const ucontext *uc,
                                 const struct _libc_fpstate* fpregs) {
   out->context_flags = MD_CONTEXT_ARM_FULL;
 
   out->iregs[0] = uc->uc_mcontext.arm_r0;
   out->iregs[1] = uc->uc_mcontext.arm_r1;
@@ -370,21 +379,21 @@ static void CPUFillFromUContext(MDRawCon
 
   //TODO: fix this after fixing ExceptionHandler
   out->float_save.fpscr = 0;
   memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
   memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
 }
 
 static uintptr_t InstructionPointer(const ThreadInfo& info) {
-  return info.regs.uregs[R12];
+  return info.regs.ARM_ip;
 }
 
 static uintptr_t StackPointer(const ThreadInfo& info) {
-  return info.regs.uregs[R13];
+  return info.regs.ARM_sp;
 }
 
 static uintptr_t StackPointer(const ucontext* uc) {
   return uc->uc_mcontext.arm_sp;
 }
 
 #else
 #error "This code has not been ported to your platform yet."
@@ -452,27 +461,28 @@ class MinidumpWriter {
   }
 
   bool Dump() {
     // The dynamic linker makes information available that helps gdb find all
     // DSOs loaded into the program. If we can access this information, we dump
     // it to a MD_LINUX_DSO_DEBUG stream.
     struct r_debug* r_debug = NULL;
     uint32_t dynamic_length = 0;
-
+#if !defined(__ANDROID__)
     for (int i = 0;;) {
       ElfW(Dyn) dyn;
       dynamic_length += sizeof(dyn);
       dumper_.CopyFromProcess(&dyn, crashing_tid_, _DYNAMIC+i++, sizeof(dyn));
       if (dyn.d_tag == DT_DEBUG) {
         r_debug = (struct r_debug*)dyn.d_un.d_ptr;
         continue;
       } else if (dyn.d_tag == DT_NULL)
         break;
     }
+#endif
 
     // A minidump file contains a number of tagged streams. This is the number
     // of stream which we write.
     unsigned kNumWriters = 12;
     if (r_debug)
       ++kNumWriters;
 
     TypedMDRVA<MDRawHeader> header(&minidump_writer_);
@@ -944,16 +954,19 @@ class MinidumpWriter {
     WriteCPUInformation(si.get());
     WriteOSInformation(si.get());
 
     return true;
   }
 
   bool WriteDSODebugStream(MDRawDirectory* dirent, struct r_debug* r_debug,
                            uint32_t dynamic_length) {
+#if defined(__ANDROID__)
+    return false;
+#else
     // The caller provided us with a pointer to "struct r_debug". We can
     // look up the "r_map" field to get a linked list of all loaded DSOs.
     // Our list of DSOs potentially is different from the ones in the crashing
     // process. So, we have to be careful to never dereference pointers
     // directly. Instead, we use CopyFromProcess() everywhere.
     // See <link.h> for a more detailed discussion of the how the dynamic
     // loader communicates with debuggers.
 
@@ -1017,16 +1030,17 @@ class MinidumpWriter {
 
     char *dso_debug_data = new char[dynamic_length];
     dumper_.CopyFromProcess(dso_debug_data, crashing_tid_, &_DYNAMIC,
                             dynamic_length);
     debug.CopyIndexAfterObject(0, dso_debug_data, dynamic_length);
     delete[] dso_debug_data;
 
     return true;
+#endif  // __ANDROID__
   }
 
  private:
 #if defined(__i386)
   uintptr_t GetInstructionPointer() {
     return ucontext_->uc_mcontext.gregs[REG_EIP];
   }
 #elif defined(__x86_64)
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in
@@ -45,19 +45,22 @@ MODULE		= breakpad_linux_common
 LIBRARY_NAME	= breakpad_linux_common_s
 HOST_LIBRARY_NAME = host_breakpad_linux_common_s
 
 LOCAL_INCLUDES 	= -I$(srcdir)/../..
 
 CPPSRCS	= \
   file_id.cc \
   guid_creator.cc \
-  http_upload.cc \
   $(NULL)
 
+ifneq (Android,$(OS_TARGET))
+CPPSRCS += http_upload.cc
+endif
+
 HOST_CPPSRCS = \
   dump_symbols.cc \
   file_id.cc \
   guid_creator.cc \
   $(NULL)
 
 # need static lib
 FORCE_STATIC_LIB = 1
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc
@@ -33,17 +33,21 @@
 //
 
 #include "common/linux/file_id.h"
 
 #include <arpa/inet.h>
 #include <assert.h>
 #include <elf.h>
 #include <fcntl.h>
+#if defined(__ANDROID__)
+#include "client/linux/android_link.h"
+#else
 #include <link.h>
+#endif
 #include <stdio.h>
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include <algorithm>
 
@@ -66,17 +70,17 @@ FileID::FileID(const char* path) {
   assert(text_size);
 
   const char* elf_base =
     static_cast<const char*>(elf_mapped_base);
   const ElfW(Ehdr)* elf_header =
     reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
   if (my_strncmp(elf_base, ELFMAG, SELFMAG) != 0)
     return false;
-#if __ELF_NATIVE_CLASS == 32
+#if __ELF_NATIVE_CLASS == 32 || ELFSIZE == 32
 #define ELFCLASS ELFCLASS32
 #else
 #define ELFCLASS ELFCLASS64
 #endif
   //TODO: support dumping 32-bit binaries from a 64-bit dump_syms?
   if (elf_header->e_ident[EI_CLASS] != ELFCLASS)
     return false;
   *text_start = NULL;
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h
@@ -1,9 +1,9 @@
-/* Copyright (c) 2005-2008, Google Inc.
+/* Copyright (c) 2005-2010, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * met:
  *
  *     * Redistributions of source code must retain the above copyright
  * notice, this list of conditions and the following disclaimer.
@@ -61,58 +61,83 @@
  *   unset SYS_LINUX_SYSCALL_SUPPORT_H before each inclusion.
  *
  * SYS_PREFIX:
  *   New system calls will have a prefix of "sys_" unless overridden by
  *   the SYS_PREFIX macro. Valid values for this macro are [0..9] which
  *   results in prefixes "sys[0..9]_". It is also possible to set this
  *   macro to -1, which avoids all prefixes.
  *
+ * SYS_SYSCALL_ENTRYPOINT:
+ *   Some applications (such as sandboxes that filter system calls), need
+ *   to be able to run custom-code each time a system call is made. If this
+ *   macro is defined, it expands to the name of a "common" symbol. If
+ *   this symbol is assigned a non-NULL pointer value, it is used as the
+ *   address of the system call entrypoint.
+ *   A pointer to this symbol can be obtained by calling
+ *   get_syscall_entrypoint()
+ *
  * This file defines a few internal symbols that all start with "LSS_".
  * Do not access these symbols from outside this file. They are not part
  * of the supported API.
  */
 #ifndef SYS_LINUX_SYSCALL_SUPPORT_H
 #define SYS_LINUX_SYSCALL_SUPPORT_H
 
 /* We currently only support x86-32, x86-64, ARM, MIPS, and PPC on Linux.
  * Porting to other related platforms should not be difficult.
  */
 #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) ||   \
      defined(__mips__) || defined(__PPC__) || defined(__ARM_EABI__)) \
-  && defined(__linux)
+  && (defined(__linux) || defined(__ANDROID__))
 
 #ifndef SYS_CPLUSPLUS
 #ifdef __cplusplus
 /* Some system header files in older versions of gcc neglect to properly
  * handle being included from C++. As it appears to be harmless to have
  * multiple nested 'extern "C"' blocks, just add another one here.
  */
 extern "C" {
 #endif
 
 #include <errno.h>
+#include <fcntl.h>
 #include <signal.h>
 #include <stdarg.h>
+#include <stddef.h>
 #include <string.h>
 #include <sys/ptrace.h>
 #include <sys/resource.h>
 #include <sys/time.h>
 #include <sys/types.h>
-#include <syscall.h>
+#include <sys/syscall.h>
 #include <unistd.h>
 #include <linux/unistd.h>
 #include <endian.h>
 
 #ifdef __mips__
 /* Include definitions of the ABI currently in use.                          */
 #include <sgidefs.h>
 #endif
 #endif
 
+/* The Android NDK #defines these. */
+#ifdef stat64
+#undef stat64
+#endif
+
+#ifdef fstat64
+#undef fstat64
+#endif
+
+#ifdef lstat64
+#undef lstat64
+#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
@@ -534,38 +559,138 @@ struct kernel_statfs {
 #define PTRACE_GETFPXREGS       ((enum __ptrace_request)18)
 #endif
 #ifndef PR_GET_DUMPABLE
 #define PR_GET_DUMPABLE         3
 #endif
 #ifndef PR_SET_DUMPABLE
 #define PR_SET_DUMPABLE         4
 #endif
+#ifndef PR_GET_SECCOMP
+#define PR_GET_SECCOMP          21
+#endif
+#ifndef PR_SET_SECCOMP
+#define PR_SET_SECCOMP          22
+#endif
 #ifndef AT_FDCWD
 #define AT_FDCWD                (-100)
 #endif
 #ifndef AT_SYMLINK_NOFOLLOW
 #define AT_SYMLINK_NOFOLLOW     0x100
 #endif
 #ifndef AT_REMOVEDIR
 #define AT_REMOVEDIR            0x200
 #endif
 #ifndef MREMAP_FIXED
 #define MREMAP_FIXED            2
 #endif
 #ifndef SA_RESTORER
 #define SA_RESTORER             0x04000000
 #endif
+#ifndef CPUCLOCK_PROF
+#define CPUCLOCK_PROF           0
+#endif
+#ifndef CPUCLOCK_VIRT
+#define CPUCLOCK_VIRT           1
+#endif
+#ifndef CPUCLOCK_SCHED
+#define CPUCLOCK_SCHED          2
+#endif
+#ifndef CPUCLOCK_PERTHREAD_MASK
+#define CPUCLOCK_PERTHREAD_MASK 4
+#endif
+#ifndef MAKE_PROCESS_CPUCLOCK
+#define MAKE_PROCESS_CPUCLOCK(pid, clock)                                     \
+        ((~(int)(pid) << 3) | (int)(clock))
+#endif
+#ifndef MAKE_THREAD_CPUCLOCK
+#define MAKE_THREAD_CPUCLOCK(tid, clock)                                      \
+        ((~(int)(tid) << 3) | (int)((clock) | CPUCLOCK_PERTHREAD_MASK))
+#endif
+
+#ifndef FUTEX_WAIT
+#define FUTEX_WAIT                0
+#endif
+#ifndef FUTEX_WAKE
+#define FUTEX_WAKE                1
+#endif
+#ifndef FUTEX_FD
+#define FUTEX_FD                  2
+#endif
+#ifndef FUTEX_REQUEUE
+#define FUTEX_REQUEUE             3
+#endif
+#ifndef FUTEX_CMP_REQUEUE
+#define FUTEX_CMP_REQUEUE         4
+#endif
+#ifndef FUTEX_WAKE_OP
+#define FUTEX_WAKE_OP             5
+#endif
+#ifndef FUTEX_LOCK_PI
+#define FUTEX_LOCK_PI             6
+#endif
+#ifndef FUTEX_UNLOCK_PI
+#define FUTEX_UNLOCK_PI           7
+#endif
+#ifndef FUTEX_TRYLOCK_PI
+#define FUTEX_TRYLOCK_PI          8
+#endif
+#ifndef FUTEX_PRIVATE_FLAG
+#define FUTEX_PRIVATE_FLAG        128
+#endif
+#ifndef FUTEX_CMD_MASK
+#define FUTEX_CMD_MASK            ~FUTEX_PRIVATE_FLAG
+#endif
+#ifndef FUTEX_WAIT_PRIVATE
+#define FUTEX_WAIT_PRIVATE        (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_WAKE_PRIVATE
+#define FUTEX_WAKE_PRIVATE        (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_REQUEUE_PRIVATE
+#define FUTEX_REQUEUE_PRIVATE     (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_CMP_REQUEUE_PRIVATE
+#define FUTEX_CMP_REQUEUE_PRIVATE (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_WAKE_OP_PRIVATE
+#define FUTEX_WAKE_OP_PRIVATE     (FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_LOCK_PI_PRIVATE
+#define FUTEX_LOCK_PI_PRIVATE     (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_UNLOCK_PI_PRIVATE
+#define FUTEX_UNLOCK_PI_PRIVATE   (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_TRYLOCK_PI_PRIVATE
+#define FUTEX_TRYLOCK_PI_PRIVATE  (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
+#endif
+
+
+#if defined(__x86_64__)
+#ifndef ARCH_SET_GS
+#define ARCH_SET_GS             0x1001
+#endif
+#ifndef ARCH_GET_GS
+#define ARCH_GET_GS             0x1004
+#endif
+#endif
 
 #if defined(__i386__)
+#ifndef __NR_quotactl
+#define __NR_quotactl           131
+#endif
 #ifndef __NR_setresuid
 #define __NR_setresuid          164
+#define __NR_getresuid          165
 #define __NR_setresgid          170
+#define __NR_getresgid          171
 #endif
 #ifndef __NR_rt_sigaction
+#define __NR_rt_sigreturn       173
 #define __NR_rt_sigaction       174
 #define __NR_rt_sigprocmask     175
 #define __NR_rt_sigpending      176
 #define __NR_rt_sigsuspend      179
 #endif
 #ifndef __NR_pread64
 #define __NR_pread64            180
 #endif
@@ -578,17 +703,19 @@ struct kernel_statfs {
 #ifndef __NR_stat64
 #define __NR_stat64             195
 #endif
 #ifndef __NR_fstat64
 #define __NR_fstat64            197
 #endif
 #ifndef __NR_setresuid32
 #define __NR_setresuid32        208
+#define __NR_getresuid32        209
 #define __NR_setresgid32        210
+#define __NR_getresgid32        211
 #endif
 #ifndef __NR_setfsuid32
 #define __NR_setfsuid32         215
 #define __NR_setfsgid32         216
 #endif
 #ifndef __NR_getdents64
 #define __NR_getdents64         220
 #endif
@@ -605,54 +732,84 @@ struct kernel_statfs {
 #define __NR_lsetxattr          227
 #endif
 #ifndef __NR_getxattr
 #define __NR_getxattr           229
 #endif
 #ifndef __NR_lgetxattr
 #define __NR_lgetxattr          230
 #endif
+#ifndef __NR_listxattr
+#define __NR_listxattr          232
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr         233
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill              238
+#endif
 #ifndef __NR_futex
 #define __NR_futex              240
 #endif
 #ifndef __NR_sched_setaffinity
 #define __NR_sched_setaffinity  241
 #define __NR_sched_getaffinity  242
 #endif
 #ifndef __NR_set_tid_address
 #define __NR_set_tid_address    258
 #endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime      265
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres       266
+#endif
 #ifndef __NR_statfs64
 #define __NR_statfs64           268
 #endif
 #ifndef __NR_fstatfs64
 #define __NR_fstatfs64          269
 #endif
 #ifndef __NR_fadvise64_64
 #define __NR_fadvise64_64       272
 #endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set         289
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get         290
+#endif
 #ifndef __NR_openat
 #define __NR_openat             295
 #endif
 #ifndef __NR_fstatat64
 #define __NR_fstatat64          300
 #endif
 #ifndef __NR_unlinkat
 #define __NR_unlinkat           301
 #endif
 #ifndef __NR_move_pages
 #define __NR_move_pages         317
 #endif
+#ifndef __NR_getcpu
+#define __NR_getcpu             318
+#endif
+#ifndef __NR_fallocate
+#define __NR_fallocate          324
+#endif
 /* End of i386 definitions                                                   */
 #elif defined(__ARM_ARCH_3__) || defined(__ARM_EABI__)
 #ifndef __NR_setresuid
 #define __NR_setresuid          (__NR_SYSCALL_BASE + 164)
+#define __NR_getresuid          (__NR_SYSCALL_BASE + 165)
 #define __NR_setresgid          (__NR_SYSCALL_BASE + 170)
+#define __NR_getresgid          (__NR_SYSCALL_BASE + 171)
 #endif
 #ifndef __NR_rt_sigaction
+#define __NR_rt_sigreturn       (__NR_SYSCALL_BASE + 173)
 #define __NR_rt_sigaction       (__NR_SYSCALL_BASE + 174)
 #define __NR_rt_sigprocmask     (__NR_SYSCALL_BASE + 175)
 #define __NR_rt_sigpending      (__NR_SYSCALL_BASE + 176)
 #define __NR_rt_sigsuspend      (__NR_SYSCALL_BASE + 179)
 #endif
 #ifndef __NR_pread64
 #define __NR_pread64            (__NR_SYSCALL_BASE + 180)
 #endif
@@ -665,17 +822,19 @@ struct kernel_statfs {
 #ifndef __NR_stat64
 #define __NR_stat64             (__NR_SYSCALL_BASE + 195)
 #endif
 #ifndef __NR_fstat64
 #define __NR_fstat64            (__NR_SYSCALL_BASE + 197)
 #endif
 #ifndef __NR_setresuid32
 #define __NR_setresuid32        (__NR_SYSCALL_BASE + 208)
+#define __NR_getresuid32        (__NR_SYSCALL_BASE + 209)
 #define __NR_setresgid32        (__NR_SYSCALL_BASE + 210)
+#define __NR_getresgid32        (__NR_SYSCALL_BASE + 211)
 #endif
 #ifndef __NR_setfsuid32
 #define __NR_setfsuid32         (__NR_SYSCALL_BASE + 215)
 #define __NR_setfsgid32         (__NR_SYSCALL_BASE + 216)
 #endif
 #ifndef __NR_getdents64
 #define __NR_getdents64         (__NR_SYSCALL_BASE + 217)
 #endif
@@ -692,40 +851,75 @@ struct kernel_statfs {
 #define __NR_lsetxattr          (__NR_SYSCALL_BASE + 227)
 #endif
 #ifndef __NR_getxattr
 #define __NR_getxattr           (__NR_SYSCALL_BASE + 229)
 #endif
 #ifndef __NR_lgetxattr
 #define __NR_lgetxattr          (__NR_SYSCALL_BASE + 230)
 #endif
+#ifndef __NR_listxattr
+#define __NR_listxattr          (__NR_SYSCALL_BASE + 232)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr         (__NR_SYSCALL_BASE + 233)
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill              (__NR_SYSCALL_BASE + 238)
+#endif
 #ifndef __NR_futex
 #define __NR_futex              (__NR_SYSCALL_BASE + 240)
 #endif
 #ifndef __NR_sched_setaffinity
 #define __NR_sched_setaffinity  (__NR_SYSCALL_BASE + 241)
 #define __NR_sched_getaffinity  (__NR_SYSCALL_BASE + 242)
 #endif
 #ifndef __NR_set_tid_address
 #define __NR_set_tid_address    (__NR_SYSCALL_BASE + 256)
 #endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime      (__NR_SYSCALL_BASE + 263)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres       (__NR_SYSCALL_BASE + 264)
+#endif
 #ifndef __NR_statfs64
 #define __NR_statfs64           (__NR_SYSCALL_BASE + 266)
 #endif
 #ifndef __NR_fstatfs64
 #define __NR_fstatfs64          (__NR_SYSCALL_BASE + 267)
 #endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set         (__NR_SYSCALL_BASE + 314)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get         (__NR_SYSCALL_BASE + 315)
+#endif
 #ifndef __NR_move_pages
 #define __NR_move_pages         (__NR_SYSCALL_BASE + 344)
 #endif
+#ifndef __NR_getcpu
+#define __NR_getcpu             (__NR_SYSCALL_BASE + 345)
+#endif
 /* End of ARM 3/EABI definitions                                                */
 #elif defined(__x86_64__)
+#ifndef __NR_pread64
+#define __NR_pread64             17
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64            18
+#endif
 #ifndef __NR_setresuid
 #define __NR_setresuid          117
+#define __NR_getresuid          118
 #define __NR_setresgid          119
+#define __NR_getresgid          120
+#endif
+#ifndef __NR_quotactl
+#define __NR_quotactl           179
 #endif
 #ifndef __NR_gettid
 #define __NR_gettid             186
 #endif
 #ifndef __NR_readahead
 #define __NR_readahead          187
 #endif
 #ifndef __NR_setxattr
@@ -735,52 +929,79 @@ struct kernel_statfs {
 #define __NR_lsetxattr          189
 #endif
 #ifndef __NR_getxattr
 #define __NR_getxattr           191
 #endif
 #ifndef __NR_lgetxattr
 #define __NR_lgetxattr          192
 #endif
+#ifndef __NR_listxattr
+#define __NR_listxattr          194
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr         195
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill              200
+#endif
 #ifndef __NR_futex
 #define __NR_futex              202
 #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_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
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres       229
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set         251
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get         252
+#endif
 #ifndef __NR_openat
 #define __NR_openat             257
 #endif
 #ifndef __NR_newfstatat
 #define __NR_newfstatat         262
 #endif
 #ifndef __NR_unlinkat
 #define __NR_unlinkat           263
 #endif
 #ifndef __NR_move_pages
 #define __NR_move_pages         279
 #endif
+#ifndef __NR_fallocate
+#define __NR_fallocate          285
+#endif
 /* End of x86-64 definitions                                                 */
 #elif defined(__mips__)
 #if _MIPS_SIM == _MIPS_SIM_ABI32
 #ifndef __NR_setresuid
 #define __NR_setresuid          (__NR_Linux + 185)
+#define __NR_getresuid          (__NR_Linux + 186)
 #define __NR_setresgid          (__NR_Linux + 190)
+#define __NR_getresgid          (__NR_Linux + 191)
 #endif
 #ifndef __NR_rt_sigaction
+#define __NR_rt_sigreturn       (__NR_Linux + 193)
 #define __NR_rt_sigaction       (__NR_Linux + 194)
 #define __NR_rt_sigprocmask     (__NR_Linux + 195)
 #define __NR_rt_sigpending      (__NR_Linux + 196)
 #define __NR_rt_sigsuspend      (__NR_Linux + 199)
 #endif
 #ifndef __NR_pread64
 #define __NR_pread64            (__NR_Linux + 200)
 #endif
@@ -809,49 +1030,81 @@ struct kernel_statfs {
 #define __NR_lsetxattr          (__NR_Linux + 225)
 #endif
 #ifndef __NR_getxattr
 #define __NR_getxattr           (__NR_Linux + 227)
 #endif
 #ifndef __NR_lgetxattr
 #define __NR_lgetxattr          (__NR_Linux + 228)
 #endif
+#ifndef __NR_listxattr
+#define __NR_listxattr          (__NR_Linux + 230)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr         (__NR_Linux + 231)
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill              (__NR_Linux + 236)
+#endif
 #ifndef __NR_futex
 #define __NR_futex              (__NR_Linux + 238)
 #endif
 #ifndef __NR_sched_setaffinity
 #define __NR_sched_setaffinity  (__NR_Linux + 239)
 #define __NR_sched_getaffinity  (__NR_Linux + 240)
 #endif
 #ifndef __NR_set_tid_address
 #define __NR_set_tid_address    (__NR_Linux + 252)
 #endif
 #ifndef __NR_statfs64
 #define __NR_statfs64           (__NR_Linux + 255)
 #endif
 #ifndef __NR_fstatfs64
 #define __NR_fstatfs64          (__NR_Linux + 256)
 #endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime      (__NR_Linux + 263)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres       (__NR_Linux + 264)
+#endif
 #ifndef __NR_openat
 #define __NR_openat             (__NR_Linux + 288)
 #endif
 #ifndef __NR_fstatat
 #define __NR_fstatat            (__NR_Linux + 293)
 #endif
 #ifndef __NR_unlinkat
 #define __NR_unlinkat           (__NR_Linux + 294)
 #endif
 #ifndef __NR_move_pages
 #define __NR_move_pages         (__NR_Linux + 308)
 #endif
+#ifndef __NR_getcpu
+#define __NR_getcpu             (__NR_Linux + 312)
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set         (__NR_Linux + 314)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get         (__NR_Linux + 315)
+#endif
 /* End of MIPS (old 32bit API) definitions */
 #elif  _MIPS_SIM == _MIPS_SIM_ABI64
+#ifndef __NR_pread64
+#define __NR_pread64            (__NR_Linux +  16)
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64           (__NR_Linux +  17)
+#endif
 #ifndef __NR_setresuid
 #define __NR_setresuid          (__NR_Linux + 115)
+#define __NR_getresuid          (__NR_Linux + 116)
 #define __NR_setresgid          (__NR_Linux + 117)
+#define __NR_getresgid          (__NR_Linux + 118)
 #endif
 #ifndef __NR_gettid
 #define __NR_gettid             (__NR_Linux + 178)
 #endif
 #ifndef __NR_readahead
 #define __NR_readahead          (__NR_Linux + 179)
 #endif
 #ifndef __NR_setxattr
@@ -861,43 +1114,69 @@ struct kernel_statfs {
 #define __NR_lsetxattr          (__NR_Linux + 181)
 #endif
 #ifndef __NR_getxattr
 #define __NR_getxattr           (__NR_Linux + 183)
 #endif
 #ifndef __NR_lgetxattr
 #define __NR_lgetxattr          (__NR_Linux + 184)
 #endif
+#ifndef __NR_listxattr
+#define __NR_listxattr          (__NR_Linux + 186)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr         (__NR_Linux + 187)
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill              (__NR_Linux + 192)
+#endif
 #ifndef __NR_futex
 #define __NR_futex              (__NR_Linux + 194)
 #endif
 #ifndef __NR_sched_setaffinity
 #define __NR_sched_setaffinity  (__NR_Linux + 195)
 #define __NR_sched_getaffinity  (__NR_Linux + 196)
 #endif
 #ifndef __NR_set_tid_address
 #define __NR_set_tid_address    (__NR_Linux + 212)
 #endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime      (__NR_Linux + 222)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres       (__NR_Linux + 223)
+#endif
 #ifndef __NR_openat
 #define __NR_openat             (__NR_Linux + 247)
 #endif
 #ifndef __NR_fstatat
 #define __NR_fstatat            (__NR_Linux + 252)
 #endif
 #ifndef __NR_unlinkat
 #define __NR_unlinkat           (__NR_Linux + 253)
 #endif
 #ifndef __NR_move_pages
 #define __NR_move_pages         (__NR_Linux + 267)
 #endif
+#ifndef __NR_getcpu
+#define __NR_getcpu             (__NR_Linux + 271)
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set         (__NR_Linux + 273)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get         (__NR_Linux + 274)
+#endif
 /* End of MIPS (64bit API) definitions */
 #else
 #ifndef __NR_setresuid
 #define __NR_setresuid          (__NR_Linux + 115)
+#define __NR_getresuid          (__NR_Linux + 116)
 #define __NR_setresgid          (__NR_Linux + 117)
+#define __NR_getresgid          (__NR_Linux + 118)
 #endif
 #ifndef __NR_gettid
 #define __NR_gettid             (__NR_Linux + 178)
 #endif
 #ifndef __NR_readahead
 #define __NR_readahead          (__NR_Linux + 179)
 #endif
 #ifndef __NR_setxattr
@@ -907,57 +1186,84 @@ struct kernel_statfs {
 #define __NR_lsetxattr          (__NR_Linux + 181)
 #endif
 #ifndef __NR_getxattr
 #define __NR_getxattr           (__NR_Linux + 183)
 #endif
 #ifndef __NR_lgetxattr
 #define __NR_lgetxattr          (__NR_Linux + 184)
 #endif
+#ifndef __NR_listxattr
+#define __NR_listxattr          (__NR_Linux + 186)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr         (__NR_Linux + 187)
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill              (__NR_Linux + 192)
+#endif
 #ifndef __NR_futex
 #define __NR_futex              (__NR_Linux + 194)
 #endif
 #ifndef __NR_sched_setaffinity
 #define __NR_sched_setaffinity  (__NR_Linux + 195)
 #define __NR_sched_getaffinity  (__NR_Linux + 196)
 #endif
 #ifndef __NR_set_tid_address
 #define __NR_set_tid_address    (__NR_Linux + 213)
 #endif
 #ifndef __NR_statfs64
 #define __NR_statfs64           (__NR_Linux + 217)
 #endif
 #ifndef __NR_fstatfs64
 #define __NR_fstatfs64          (__NR_Linux + 218)
 #endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime      (__NR_Linux + 226)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres       (__NR_Linux + 227)
+#endif
 #ifndef __NR_openat
 #define __NR_openat             (__NR_Linux + 251)
 #endif
 #ifndef __NR_fstatat
 #define __NR_fstatat            (__NR_Linux + 256)
 #endif
 #ifndef __NR_unlinkat
 #define __NR_unlinkat           (__NR_Linux + 257)
 #endif
 #ifndef __NR_move_pages
 #define __NR_move_pages         (__NR_Linux + 271)
 #endif
+#ifndef __NR_getcpu
+#define __NR_getcpu             (__NR_Linux + 275)
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set         (__NR_Linux + 277)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get         (__NR_Linux + 278)
+#endif
 /* End of MIPS (new 32bit API) definitions                                   */
 #endif
 /* End of MIPS definitions                                                   */
 #elif defined(__PPC__)
 #ifndef __NR_setfsuid
 #define __NR_setfsuid           138
 #define __NR_setfsgid           139
 #endif
 #ifndef __NR_setresuid
 #define __NR_setresuid          164
+#define __NR_getresuid          165
 #define __NR_setresgid          169
+#define __NR_getresgid          170
 #endif
 #ifndef __NR_rt_sigaction
+#define __NR_rt_sigreturn       172
 #define __NR_rt_sigaction       173
 #define __NR_rt_sigprocmask     174
 #define __NR_rt_sigpending      175
 #define __NR_rt_sigsuspend      178
 #endif
 #ifndef __NR_pread64
 #define __NR_pread64            179
 #endif
@@ -977,59 +1283,83 @@ struct kernel_statfs {
 #define __NR_fstat64            197
 #endif
 #ifndef __NR_getdents64
 #define __NR_getdents64         202
 #endif
 #ifndef __NR_gettid
 #define __NR_gettid             207
 #endif
+#ifndef __NR_tkill
+#define __NR_tkill              208
+#endif
 #ifndef __NR_setxattr
 #define __NR_setxattr           209
 #endif
 #ifndef __NR_lsetxattr
 #define __NR_lsetxattr          210
 #endif
 #ifndef __NR_getxattr
 #define __NR_getxattr           212
 #endif
 #ifndef __NR_lgetxattr
 #define __NR_lgetxattr          213
 #endif
+#ifndef __NR_listxattr
+#define __NR_listxattr          215
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr         216
+#endif
 #ifndef __NR_futex
 #define __NR_futex              221
 #endif
 #ifndef __NR_sched_setaffinity
 #define __NR_sched_setaffinity  222
 #define __NR_sched_getaffinity  223
 #endif
 #ifndef __NR_set_tid_address
 #define __NR_set_tid_address    232
 #endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime      246
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres       247
+#endif
 #ifndef __NR_statfs64
 #define __NR_statfs64           252
 #endif
 #ifndef __NR_fstatfs64
 #define __NR_fstatfs64          253
 #endif
 #ifndef __NR_fadvise64_64
 #define __NR_fadvise64_64       254
 #endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set         273
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get         274
+#endif
 #ifndef __NR_openat
 #define __NR_openat             286
 #endif
 #ifndef __NR_fstatat64
 #define __NR_fstatat64          291
 #endif
 #ifndef __NR_unlinkat
 #define __NR_unlinkat           292
 #endif
 #ifndef __NR_move_pages
 #define __NR_move_pages         301
 #endif
+#ifndef __NR_getcpu
+#define __NR_getcpu             302
+#endif
 /* End of powerpc defininitions                                              */
 #endif
 
 
 /* After forking, we must make sure to only call system calls.               */
 #if __BOUNDED_POINTERS__
   #error "Need to port invocations of syscalls for bounded ptrs"
 #else
@@ -1130,34 +1460,76 @@ struct kernel_statfs {
     /* In PIC mode (e.g. when building shared libraries), gcc for i386
      * reserves ebx. Unfortunately, most distribution ship with implementations
      * of _syscallX() which clobber ebx.
      * Also, most definitions of _syscallX() neglect to mark "memory" as being
      * clobbered. This causes problems with compilers, that do a better job
      * at optimizing across __asm__ calls.
      * So, we just have to redefine all of the _syscallX() macros.
      */
+    #undef LSS_ENTRYPOINT
+    #ifdef SYS_SYSCALL_ENTRYPOINT
+    static inline void (**LSS_NAME(get_syscall_entrypoint)(void))(void) {
+      void (**entrypoint)(void);
+      asm volatile(".bss\n"
+                   ".align 8\n"
+                   ".globl "SYS_SYSCALL_ENTRYPOINT"\n"
+                   ".common "SYS_SYSCALL_ENTRYPOINT",8,8\n"
+                   ".previous\n"
+                   /* This logically does 'lea "SYS_SYSCALL_ENTRYPOINT", %0' */
+                   "call 0f\n"
+                 "0:pop  %0\n"
+                   "add  $_GLOBAL_OFFSET_TABLE_+[.-0b], %0\n"
+                   "mov  "SYS_SYSCALL_ENTRYPOINT"@GOT(%0), %0\n"
+                   : "=r"(entrypoint));
+      return entrypoint;
+    }
+
+    #define LSS_ENTRYPOINT ".bss\n"                                           \
+                           ".align 8\n"                                       \
+                           ".globl "SYS_SYSCALL_ENTRYPOINT"\n"                \
+                           ".common "SYS_SYSCALL_ENTRYPOINT",8,8\n"           \
+                           ".previous\n"                                      \
+                           /* Check the SYS_SYSCALL_ENTRYPOINT vector      */ \
+                           "push %%eax\n"                                     \
+                           "call 10000f\n"                                    \
+                     "10000:pop  %%eax\n"                                     \
+                           "add  $_GLOBAL_OFFSET_TABLE_+[.-10000b], %%eax\n"  \
+                           "mov  "SYS_SYSCALL_ENTRYPOINT"@GOT(%%eax), %%eax\n"\
+                           "mov  0(%%eax), %%eax\n"                           \
+                           "test %%eax, %%eax\n"                              \
+                           "jz   10001f\n"                                    \
+                           "push %%eax\n"                                     \
+                           "lea  10002f, %%eax\n"                             \
+                           "xchg 4(%%esp), %%eax\n"                           \
+                           "ret\n"                                            \
+                     "10001:pop  %%eax\n"                                     \
+                           "int $0x80\n"                                      \
+                     "10002:\n"
+    #else
+    #define LSS_ENTRYPOINT "int $0x80\n"
+    #endif
     #undef  LSS_BODY
     #define LSS_BODY(type,args...)                                            \
       long __res;                                                             \
       __asm__ __volatile__("push %%ebx\n"                                     \
                            "movl %2,%%ebx\n"                                  \
-                           "int $0x80\n"                                      \
+                           LSS_ENTRYPOINT                                     \
                            "pop %%ebx"                                        \
                            args                                               \
-                           : "memory");                                       \
+                           : "esp", "memory");                                \
       LSS_RETURN(type,__res)
     #undef  _syscall0
     #define _syscall0(type,name)                                              \
       type LSS_NAME(name)(void) {                                             \
         long __res;                                                           \
-        __asm__ volatile("int $0x80"                                          \
+        __asm__ volatile(LSS_ENTRYPOINT                                       \
                          : "=a" (__res)                                       \
                          : "0" (__NR_##name)                                  \
-                         : "memory");                                         \
+                         : "esp", "memory");                                  \
         LSS_RETURN(type,__res);                                               \
       }
     #undef  _syscall1
     #define _syscall1(type,name,type1,arg1)                                   \
       type LSS_NAME(name)(type1 arg1) {                                       \
         LSS_BODY(type,                                                        \
              : "=a" (__res)                                                   \
              : "0" (__NR_##name), "ri" ((long)(arg1)));                       \
@@ -1189,45 +1561,45 @@ struct kernel_statfs {
     #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,  \
                       type5,arg5)                                             \
       type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4,     \
                           type5 arg5) {                                       \
         long __res;                                                           \
         __asm__ __volatile__("push %%ebx\n"                                   \
                              "movl %2,%%ebx\n"                                \
                              "movl %1,%%eax\n"                                \
-                             "int  $0x80\n"                                   \
+                             LSS_ENTRYPOINT                                   \
                              "pop  %%ebx"                                     \
                              : "=a" (__res)                                   \
                              : "i" (__NR_##name), "ri" ((long)(arg1)),        \
                                "c" ((long)(arg2)), "d" ((long)(arg3)),        \
                                "S" ((long)(arg4)), "D" ((long)(arg5))         \
-                             : "memory");                                     \
+                             : "esp", "memory");                              \
         LSS_RETURN(type,__res);                                               \
       }
     #undef  _syscall6
     #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,  \
                       type5,arg5,type6,arg6)                                  \
       type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4,     \
                           type5 arg5, type6 arg6) {                           \
         long __res;                                                           \
         struct { long __a1; long __a6; } __s = { (long)arg1, (long) arg6 };   \
         __asm__ __volatile__("push %%ebp\n"                                   \
                              "push %%ebx\n"                                   \
                              "movl 4(%2),%%ebp\n"                             \
                              "movl 0(%2), %%ebx\n"                            \
                              "movl %1,%%eax\n"                                \
-                             "int  $0x80\n"                                   \
+                             LSS_ENTRYPOINT                                   \
                              "pop  %%ebx\n"                                   \
                              "pop  %%ebp"                                     \
                              : "=a" (__res)                                   \
                              : "i" (__NR_##name),  "0" ((long)(&__s)),        \
                                "c" ((long)(arg2)), "d" ((long)(arg3)),        \
                                "S" ((long)(arg4)), "D" ((long)(arg5))         \
-                             : "memory");                                     \
+                             : "esp", "memory");                              \
         LSS_RETURN(type,__res);                                               \
       }
     LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
                                    int flags, void *arg, int *parent_tidptr,
                                    void *newtls, int *child_tidptr) {
       long __res;
       __asm__ __volatile__(/* if (fn == NULL)
                             *   return -EINVAL;
@@ -1266,17 +1638,17 @@ struct kernel_statfs {
                             */
                            "movl   %8,%%esi\n"
                            "movl   %7,%%edx\n"
                            "movl   %5,%%eax\n"
                            "movl   %9,%%edi\n"
                            "pushl  %%ebx\n"
                            "movl   %%eax,%%ebx\n"
                            "movl   %2,%%eax\n"
-                           "int    $0x80\n"
+                           LSS_ENTRYPOINT
 
                            /* In the parent: restore %ebx
                             * In the child:  move "fn" into %ebx
                             */
                            "popl   %%ebx\n"
 
                            /* if (%eax != 0)
                             *   return %eax;
@@ -1294,26 +1666,26 @@ struct kernel_statfs {
 
                            /* Call _exit(%ebx). Unfortunately older versions
                             * of gcc restrict the number of arguments that can
                             * be passed to asm(). So, we need to hard-code the
                             * system call number.
                             */
                            "movl   %%eax,%%ebx\n"
                            "movl   $1,%%eax\n"
-                           "int    $0x80\n"
+                           LSS_ENTRYPOINT
 
                            /* Return to parent.
                             */
                          "1:\n"
                            : "=a" (__res)
                            : "0"(-EINVAL), "i"(__NR_clone),
                              "m"(fn), "m"(child_stack), "m"(flags), "m"(arg),
                              "m"(parent_tidptr), "m"(newtls), "m"(child_tidptr)
-                           : "memory", "ecx", "edx", "esi", "edi");
+                           : "esp", "memory", "ecx", "edx", "esi", "edi");
       LSS_RETURN(int, __res);
     }
 
     #define __NR__fadvise64_64 __NR_fadvise64_64
     LSS_INLINE _syscall6(int, _fadvise64_64, int, fd,
                          unsigned, offset_lo, unsigned, offset_hi,
                          unsigned, len_lo, unsigned, len_hi,
                          int, advice)
@@ -1321,28 +1693,43 @@ struct kernel_statfs {
     LSS_INLINE int LSS_NAME(fadvise64)(int fd, loff_t offset,
                                        loff_t len, int advice) {
       return LSS_NAME(_fadvise64_64)(fd,
                                      (unsigned)offset, (unsigned)(offset >>32),
                                      (unsigned)len, (unsigned)(len >> 32),
                                      advice);
     }
 
+    #define __NR__fallocate __NR_fallocate
+    LSS_INLINE _syscall6(int, _fallocate, int, fd,
+                         int, mode,
+                         unsigned, offset_lo, unsigned, offset_hi,
+                         unsigned, len_lo, unsigned, len_hi)
+
+    LSS_INLINE int LSS_NAME(fallocate)(int fd, int mode,
+                                       loff_t offset, loff_t len) {
+      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]);
+    }
+
+    LSS_INLINE _syscall1(int, set_thread_area, void *, u)
+    LSS_INLINE _syscall1(int, get_thread_area, void *, u)
+
     LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) {
       /* On i386, the kernel does not know how to return from a signal
        * handler. Instead, it relies on user space to provide a
        * restorer function that calls the {rt_,}sigreturn() system call.
        * Unfortunately, we cannot just reference the glibc version of this
        * function, as glibc goes out of its way to make it inaccessible.
        */
       void (*res)(void);
       __asm__ __volatile__("call   2f\n"
                          "0:.align 16\n"
                          "1:movl   %1,%%eax\n"
-                           "int    $0x80\n"
+                           LSS_ENTRYPOINT
                          "2:popl   %0\n"
                            "addl   $(1b-0b),%0\n"
                            : "=a" (res)
                            : "i"  (__NR_rt_sigreturn));
       return res;
     }
     LSS_INLINE void (*LSS_NAME(restore)(void))(void) {
       /* On i386, the kernel does not know how to return from a signal
@@ -1351,34 +1738,67 @@ struct kernel_statfs {
        * Unfortunately, we cannot just reference the glibc version of this
        * function, as glibc goes out of its way to make it inaccessible.
        */
       void (*res)(void);
       __asm__ __volatile__("call   2f\n"
                          "0:.align 16\n"
                          "1:pop    %%eax\n"
                            "movl   %1,%%eax\n"
-                           "int    $0x80\n"
+                           LSS_ENTRYPOINT
                          "2:popl   %0\n"
                            "addl   $(1b-0b),%0\n"
                            : "=a" (res)
                            : "i"  (__NR_sigreturn));
       return res;
     }
   #elif defined(__x86_64__)
     /* There are no known problems with any of the _syscallX() macros
      * currently shipping for x86_64, but we still need to be able to define
      * our own version so that we can override the location of the errno
      * location (e.g. when using the clone() system call with the CLONE_VM
      * option).
      */
+    #undef LSS_ENTRYPOINT
+    #ifdef SYS_SYSCALL_ENTRYPOINT
+    static inline void (**LSS_NAME(get_syscall_entrypoint)(void))(void) {
+      void (**entrypoint)(void);
+      asm volatile(".bss\n"
+                   ".align 8\n"
+                   ".globl "SYS_SYSCALL_ENTRYPOINT"\n"
+                   ".common "SYS_SYSCALL_ENTRYPOINT",8,8\n"
+                   ".previous\n"
+                   "mov "SYS_SYSCALL_ENTRYPOINT"@GOTPCREL(%%rip), %0\n"
+                   : "=r"(entrypoint));
+      return entrypoint;
+    }
+
+    #define LSS_ENTRYPOINT                                                    \
+              ".bss\n"                                                        \
+              ".align 8\n"                                                    \
+              ".globl "SYS_SYSCALL_ENTRYPOINT"\n"                             \
+              ".common "SYS_SYSCALL_ENTRYPOINT",8,8\n"                        \
+              ".previous\n"                                                   \
+              "mov "SYS_SYSCALL_ENTRYPOINT"@GOTPCREL(%%rip), %%rcx\n"         \
+              "mov  0(%%rcx), %%rcx\n"                                        \
+              "test %%rcx, %%rcx\n"                                           \
+              "jz   10001f\n"                                                 \
+              "call *%%rcx\n"                                                 \
+              "jmp  10002f\n"                                                 \
+        "10001:syscall\n"                                                     \
+        "10002:\n"
+
+    #else
+    #define LSS_ENTRYPOINT "syscall\n"
+    #endif
     #undef  LSS_BODY
     #define LSS_BODY(type,name, ...)                                          \
           long __res;                                                         \
-          __asm__ __volatile__("syscall" : "=a" (__res) : "0" (__NR_##name),  \
+          __asm__ __volatile__(LSS_ENTRYPOINT                                 \
+            : "=a" (__res) : "0" (__NR_##name),                               \
             ##__VA_ARGS__ : "r11", "rcx", "memory");                          \
           LSS_RETURN(type, __res)
     #undef _syscall0
     #define _syscall0(type,name)                                              \
       type LSS_NAME(name)() {                                                 \
         LSS_BODY(type, name);                                                 \
       }
     #undef _syscall1
@@ -1396,46 +1816,46 @@ struct kernel_statfs {
       type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) {               \
         LSS_BODY(type, name, "D" ((long)(arg1)), "S" ((long)(arg2)),          \
                              "d" ((long)(arg3)));                             \
       }
     #undef _syscall4
     #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)  \
       type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {   \
           long __res;                                                         \
-          __asm__ __volatile__("movq %5,%%r10; syscall" :                     \
+          __asm__ __volatile__("movq %5,%%r10;" LSS_ENTRYPOINT :              \
             "=a" (__res) : "0" (__NR_##name),                                 \
             "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)),       \
-            "g" ((long)(arg4)) : "r10", "r11", "rcx", "memory");              \
+            "r" ((long)(arg4)) : "r10", "r11", "rcx", "memory");              \
           LSS_RETURN(type, __res);                                            \
       }
     #undef _syscall5
     #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,  \
                       type5,arg5)                                             \
       type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4,     \
                           type5 arg5) {                                       \
           long __res;                                                         \
-          __asm__ __volatile__("movq %5,%%r10; movq %6,%%r8; syscall" :       \
+          __asm__ __volatile__("movq %5,%%r10; movq %6,%%r8;" LSS_ENTRYPOINT :\
             "=a" (__res) : "0" (__NR_##name),                                 \
             "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)),       \
-            "g" ((long)(arg4)), "g" ((long)(arg5)) :                          \
+            "r" ((long)(arg4)), "r" ((long)(arg5)) :                          \
             "r8", "r10", "r11", "rcx", "memory");                             \
           LSS_RETURN(type, __res);                                            \
       }
     #undef _syscall6
     #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,  \
                       type5,arg5,type6,arg6)                                  \
       type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4,     \
                           type5 arg5, type6 arg6) {                           \
           long __res;                                                         \
           __asm__ __volatile__("movq %5,%%r10; movq %6,%%r8; movq %7,%%r9;"   \
-                               "syscall" :                                    \
+                               LSS_ENTRYPOINT :                               \
             "=a" (__res) : "0" (__NR_##name),                                 \
             "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)),       \
-            "g" ((long)(arg4)), "g" ((long)(arg5)), "g" ((long)(arg6)) :      \
+            "r" ((long)(arg4)), "r" ((long)(arg5)), "r" ((long)(arg6)) :      \
             "r8", "r9", "r10", "r11", "rcx", "memory");                       \
           LSS_RETURN(type, __res);                                            \
       }
     LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
                                    int flags, void *arg, int *parent_tidptr,
                                    void *newtls, int *child_tidptr) {
       long __res;
       {
@@ -1466,17 +1886,17 @@ struct kernel_statfs {
                              /* %rax = syscall(%rax = __NR_clone,
                               *                %rdi = flags,
                               *                %rsi = child_stack,
                               *                %rdx = parent_tidptr,
                               *                %r8  = new_tls,
                               *                %r10 = child_tidptr)
                               */
                              "movq   %2,%%rax\n"
-                             "syscall\n"
+                             LSS_ENTRYPOINT
 
                              /* if (%rax != 0)
                               *   return;
                               */
                              "testq  %%rax,%%rax\n"
                              "jnz    1f\n"
 
                              /* In the child. Terminate frame pointer chain.
@@ -1488,51 +1908,57 @@ struct kernel_statfs {
                              "popq   %%rax\n"
                              "popq   %%rdi\n"
                              "call   *%%rax\n"
 
                              /* Call _exit(%ebx).
                               */
                              "movq   %%rax,%%rdi\n"
                              "movq   %3,%%rax\n"
-                             "syscall\n"
+                             LSS_ENTRYPOINT
 
                              /* Return to parent.
                               */
                            "1:\n"
                              : "=a" (__res)
                              : "0"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit),
                                "r"(fn), "S"(child_stack), "D"(flags), "r"(arg),
                                "d"(parent_tidptr), "r"(__tls), "r"(__ctid)
-                             : "memory", "r11", "rcx");
+                             : "rsp", "memory", "r11", "rcx");
       }
       LSS_RETURN(int, __res);
     }
+    LSS_INLINE _syscall2(int, arch_prctl, int, c, void *, a)
     LSS_INLINE _syscall4(int, fadvise64, int, fd, loff_t, offset, loff_t, len,
                          int,  advice)
 
     LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) {
       /* On x86-64, the kernel does not know how to return from
        * a signal handler. Instead, it relies on user space to provide a
        * restorer function that calls the rt_sigreturn() system call.
        * Unfortunately, we cannot just reference the glibc version of this
        * function, as glibc goes out of its way to make it inaccessible.
        */
       void (*res)(void);
       __asm__ __volatile__("call   2f\n"
                          "0:.align 16\n"
                          "1:movq   %1,%%rax\n"
-                           "syscall\n"
+                           LSS_ENTRYPOINT
                          "2:popq   %0\n"
                            "addq   $(1b-0b),%0\n"
                            : "=a" (res)
                            : "i"  (__NR_rt_sigreturn));
       return res;
     }
   #elif defined(__ARM_ARCH_3__)
+    /* Most definitions of _syscallX() neglect to mark "memory" as being
+     * clobbered. This causes problems with compilers, that do a better job
+     * at optimizing across __asm__ calls.
+     * So, we just have to redefine all of the _syscallX() macros.
+     */
     #undef LSS_REG
     #define LSS_REG(r,a) register long __r##r __asm__("r"#r) = (long)a
     #undef  LSS_BODY
     #define LSS_BODY(type,name,args...)                                       \
           register long __res_r0 __asm__("r0");                               \
           long __res;                                                         \
           __asm__ __volatile__ (__syscall(name)                               \
                                 : "=r"(__res_r0) : args : "lr", "memory");    \
@@ -1722,17 +2148,19 @@ struct kernel_statfs {
         register void *__stack __asm__("r1") = child_stack;
         register void *__ptid  __asm__("r2") = parent_tidptr;
         register void *__tls   __asm__("r3") = newtls;
         register int  *__ctid  __asm__("r4") = child_tidptr;
         __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL)
                               *   return -EINVAL;
                               */
                              "cmp   %2,#0\n"
+                             "it    ne\n"
                              "cmpne %3,#0\n"
+                             "it    eq\n"
                              "moveq %0,%1\n"
                              "beq   1f\n"
 
                              /* Push "arg" and "fn" onto the stack that will be
                               * used by the child.
                               */
                              "str   %5,[%3,#-4]!\n"
                              "str   %2,[%3,#-4]!\n"
@@ -2174,45 +2602,57 @@ struct kernel_statfs {
                 "r0", "r29", "r27", "r28");
       }
       LSS_RETURN(int, __ret, __err);
     }
   #endif
   #define __NR__exit   __NR_exit
   #define __NR__gettid __NR_gettid
   #define __NR__mremap __NR_mremap
+  LSS_INLINE _syscall1(int,     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)
   LSS_INLINE _syscall2(int,     dup2,            int,         s,
                        int,            d)
   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)
   LSS_INLINE _syscall0(pid_t,   fork)
   LSS_INLINE _syscall2(int,     fstat,           int,         f,
                       struct kernel_stat*,   b)
   LSS_INLINE _syscall2(int,     fstatfs,         int,         f,
                       struct kernel_statfs*, b)
+  LSS_INLINE _syscall2(int, ftruncate,           int,         f,
+                       off_t,          l)
   LSS_INLINE _syscall4(int,     futex,           int*,        a,
                        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)
   LSS_INLINE _syscall0(pid_t,   getpgrp)
   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)
+  LSS_INLINE _syscall3(int,     getresuid,       uid_t *,     r,
+                       uid_t *,         e,       uid_t *,     s)
 #if !defined(__ARM_EABI__)
   LSS_INLINE _syscall2(int,     getrlimit,       int,         r,
                       struct kernel_rlimit*, l)
 #endif
   LSS_INLINE _syscall1(pid_t,   getsid,          pid_t,       p)
   LSS_INLINE _syscall0(pid_t,   _gettid)
   LSS_INLINE _syscall2(pid_t,   gettimeofday,    struct kernel_timeval*, t,
                        void*, tz)
@@ -2221,36 +2661,53 @@ struct kernel_statfs {
                        size_t,         s,        int,         f)
   LSS_INLINE _syscall5(int,     lsetxattr,       const char *,p,
                        const char *,   n,        const void *,v,
                        size_t,         s,        int,         f)
   LSS_INLINE _syscall4(ssize_t, getxattr,        const char *,p,
                        const char *,   n,        void *,      v, size_t, s)
   LSS_INLINE _syscall4(ssize_t, lgetxattr,       const char *,p,
                        const char *,   n,        void *,      v, size_t, s)
+  LSS_INLINE _syscall3(ssize_t, listxattr,       const char *,p,
+                       char *,   l,              size_t,      s)
+  LSS_INLINE _syscall3(ssize_t, llistxattr,      const char *,p,
+                       char *,   l,              size_t,      s)
+  LSS_INLINE _syscall3(int,     ioctl,           int,         d,
+                       int,     r,               void *,      a)
+  LSS_INLINE _syscall2(int,     ioprio_get,      int,         which,
+                       int,     who)
+  LSS_INLINE _syscall3(int,     ioprio_set,      int,         which,
+                       int,     who,             int,         ioprio)
   LSS_INLINE _syscall2(int,     kill,            pid_t,       p,
                        int,            s)
   LSS_INLINE _syscall3(off_t,   lseek,           int,         f,
                        off_t,          o, int,    w)
   LSS_INLINE _syscall2(int,     munmap,          void*,       s,
                        size_t,         l)
   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)
   LSS_INLINE _syscall3(int,     open,            const char*, p,
                        int,            f, int,    m)
   LSS_INLINE _syscall3(int,     poll,           struct kernel_pollfd*, u,
                        unsigned int,   n, int,    t)
   LSS_INLINE _syscall2(int,     prctl,           int,         o,
                        long,           a)
   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)
   LSS_INLINE _syscall3(int,     readlink,        const char*, p,
                        char*,          b, size_t, s)
   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,
@@ -2263,38 +2720,51 @@ struct kernel_statfs {
   LSS_INLINE _syscall3(int,     sched_getaffinity,pid_t,      p,
                        unsigned int,   l, unsigned long *, m)
   LSS_INLINE _syscall3(int,     sched_setaffinity,pid_t,      p,
                        unsigned int,   l, unsigned long *, m)
   LSS_INLINE _syscall0(int,     sched_yield)
   LSS_INLINE _syscall1(long,    set_tid_address, int *,       t)
   LSS_INLINE _syscall1(int,     setfsgid,        gid_t,       g)
   LSS_INLINE _syscall1(int,     setfsuid,        uid_t,       u)
+  LSS_INLINE _syscall1(int,     setuid,          uid_t,       u)
+  LSS_INLINE _syscall1(int,     setgid,          gid_t,       g)
   LSS_INLINE _syscall2(int,     setpgid,         pid_t,       p,
                        pid_t,          g)
   LSS_INLINE _syscall3(int,     setpriority,     int,         a,
                        int,            b, int,    p)
   LSS_INLINE _syscall3(int,     setresgid,       gid_t,       r,
                        gid_t,          e, gid_t,  s)
   LSS_INLINE _syscall3(int,     setresuid,       uid_t,       r,
                        uid_t,          e, uid_t,  s)
   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
   LSS_INLINE _syscall2(int,     stat,            const char*, f,
                       struct kernel_stat*,   b)
   LSS_INLINE _syscall2(int,     statfs,          const char*, f,
                       struct kernel_statfs*, b)
-  LSS_INLINE _syscall1(int,    unlink,          const char*, f)
+  LSS_INLINE _syscall3(int,     tgkill,          pid_t,       p,
+                       pid_t,          t, int,            s)
+  LSS_INLINE _syscall2(int,     tkill,           pid_t,       p,
+                       int,            s)
+  LSS_INLINE _syscall1(int,     unlink,           const char*, f)
   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,
+                         unsigned *, node, void *, unused);
+  #endif
   #if defined(__x86_64__) ||                                                  \
      (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32)
     LSS_INLINE _syscall3(int, recvmsg,            int,   s,
                         struct kernel_msghdr*,     m, int, f)
     LSS_INLINE _syscall3(int, sendmsg,            int,   s,
                          const struct kernel_msghdr*, m, int, f)
     LSS_INLINE _syscall6(int, sendto,             int,   s,
                          const void*,             m, size_t, l,
@@ -2303,20 +2773,36 @@ struct kernel_statfs {
     LSS_INLINE _syscall2(int, shutdown,           int,   s,
                          int,                     h)
     LSS_INLINE _syscall3(int, socket,             int,   d,
                          int,                     t, int,       p)
     LSS_INLINE _syscall4(int, socketpair,         int,   d,
                          int,                     t, int,       p, int*, s)
   #endif
   #if defined(__x86_64__)
+    LSS_INLINE _syscall4(int, fallocate, int, fd, int, mode,
+                         loff_t, offset, loff_t, len)
+
+    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 _syscall6(void*, mmap,              void*, s,
                          size_t,                   l, int,               p,
                          int,                      f, int,               d,
                          __off64_t,                o)
+
     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);
     }
 
@@ -2377,30 +2863,68 @@ struct kernel_statfs {
       return LSS_NAME(wait4)(pid, status, options, 0);
     }
   #endif
   #if defined(__i386__) || defined(__x86_64__)
     LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m)
     LSS_INLINE _syscall3(int, unlinkat, int, d, const char *, p, int, f)
   #endif
   #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__)
+    #define __NR__getresgid32 __NR_getresgid32
+    #define __NR__getresuid32 __NR_getresuid32
     #define __NR__setfsgid32  __NR_setfsgid32
     #define __NR__setfsuid32  __NR_setfsuid32
     #define __NR__setresgid32 __NR_setresgid32
     #define __NR__setresuid32 __NR_setresuid32
 #if defined(__ARM_EABI__)
     LSS_INLINE _syscall2(int,   ugetrlimit,        int,          r,
                         struct kernel_rlimit*, l)
 #endif
-    LSS_INLINE _syscall1(int,     _setfsgid32,      gid_t,       f)
-    LSS_INLINE _syscall1(int,     _setfsuid32,      uid_t,       f)
-    LSS_INLINE _syscall3(int,     _setresgid32,    gid_t,       r,
-                         gid_t,          e, gid_t,  s)
-    LSS_INLINE _syscall3(int,     _setresuid32,    uid_t,       r,
-                         uid_t,          e, uid_t,  s)
+    LSS_INLINE _syscall3(int,     _getresgid32,    gid_t *,      r,
+                         gid_t *,            e,    gid_t *,      s)
+    LSS_INLINE _syscall3(int,     _getresuid32,    uid_t *,      r,
+                         uid_t *,            e,    uid_t *,      s)
+    LSS_INLINE _syscall1(int,     _setfsgid32,     gid_t,        f)
+    LSS_INLINE _syscall1(int,     _setfsuid32,     uid_t,        f)
+    LSS_INLINE _syscall3(int,     _setresgid32,    gid_t,        r,
+                         gid_t,              e,    gid_t,        s)
+    LSS_INLINE _syscall3(int,     _setresuid32,    uid_t,        r,
+                         uid_t,              e,    uid_t,        s)
+
+    LSS_INLINE int LSS_NAME(getresgid32)(gid_t *rgid,
+                                         gid_t *egid,
+                                         gid_t *sgid) {
+      int rc;
+      if ((rc = LSS_NAME(_getresgid32)(rgid, egid, sgid)) < 0 &&
+          LSS_ERRNO == ENOSYS) {
+        if ((rgid == NULL) || (egid == NULL) || (sgid == NULL)) {
+          return EFAULT;
+        }
+        // Clear the high bits first, since getresgid only sets 16 bits
+        *rgid = *egid = *sgid = 0;
+        rc = LSS_NAME(getresgid)(rgid, egid, sgid);
+      }
+      return rc;
+    }
+
+    LSS_INLINE int LSS_NAME(getresuid32)(uid_t *ruid,
+                                         uid_t *euid,
+                                         uid_t *suid) {
+      int rc;
+      if ((rc = LSS_NAME(_getresuid32)(ruid, euid, suid)) < 0 &&
+          LSS_ERRNO == ENOSYS) {
+        if ((ruid == NULL) || (euid == NULL) || (suid == NULL)) {
+          return EFAULT;
+        }
+        // Clear the high bits first, since getresuid only sets 16 bits
+        *ruid = *euid = *suid = 0;
+        rc = LSS_NAME(getresuid)(ruid, euid, suid);
+      }
+      return rc;
+    }
 
     LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) {
       int rc;
       if ((rc = LSS_NAME(_setfsgid32)(gid)) < 0 &&
           LSS_ERRNO == ENOSYS) {
         if ((unsigned int)gid & ~0xFFFFu) {
           rc = EINVAL;
         } else {
@@ -2452,34 +2976,34 @@ struct kernel_statfs {
       }
       return rc;
     }
   #endif
   LSS_INLINE int LSS_NAME(sigemptyset)(struct kernel_sigset_t *set) {
     memset(&set->sig, 0, sizeof(set->sig));
     return 0;
   }
-  
+
   LSS_INLINE int LSS_NAME(sigfillset)(struct kernel_sigset_t *set) {
     memset(&set->sig, -1, sizeof(set->sig));
     return 0;
   }
-  
+
   LSS_INLINE int LSS_NAME(sigaddset)(struct kernel_sigset_t *set,
                                      int signum) {
     if (signum < 1 || signum > (int)(8*sizeof(set->sig))) {
       LSS_ERRNO = EINVAL;
       return -1;
     } else {
       set->sig[(signum - 1)/(8*sizeof(set->sig[0]))]
           |= 1UL << ((signum - 1) % (8*sizeof(set->sig[0])));
       return 0;
     }
   }
-  
+
   LSS_INLINE int LSS_NAME(sigdelset)(struct kernel_sigset_t *set,
                                         int signum) {
     if (signum < 1 || signum > (int)(8*sizeof(set->sig))) {
       LSS_ERRNO = EINVAL;
       return -1;
     } else {
       set->sig[(signum - 1)/(8*sizeof(set->sig[0]))]
           &= ~(1UL << ((signum - 1) % (8*sizeof(set->sig[0]))));
@@ -2502,25 +3026,26 @@ struct kernel_statfs {
      (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || defined(__PPC__)
     #define __NR__sigaction   __NR_sigaction
     #define __NR__sigpending  __NR_sigpending
     #define __NR__sigprocmask __NR_sigprocmask
     #define __NR__sigsuspend  __NR_sigsuspend
     #define __NR__socketcall  __NR_socketcall
     LSS_INLINE _syscall2(int, fstat64,             int, f,
                          struct kernel_stat64 *, b)
-    LSS_INLINE _syscall5(int, _llseek,     uint, fd, ulong, hi, ulong, lo,
+    LSS_INLINE _syscall5(int, _llseek,     uint, fd,
+                         unsigned long, hi, unsigned long, lo,
                          loff_t *, res, uint, wh)
 #if !defined(__ARM_EABI__)
     LSS_INLINE _syscall1(void*, mmap,              void*, a)
 #endif
     LSS_INLINE _syscall6(void*, mmap2,             void*, s,
                          size_t,                   l, int,               p,
                          int,                      f, int,               d,
-                         __off64_t,                o)
+                         off_t,                o)
     LSS_INLINE _syscall3(int,   _sigaction,        int,   s,
                          const struct kernel_old_sigaction*,  a,
                          struct kernel_old_sigaction*,        o)
     LSS_INLINE _syscall1(int,   _sigpending, unsigned long*, s)
     LSS_INLINE _syscall3(int,   _sigprocmask,      int,   h,
                          const unsigned long*,     s,
                          unsigned long*,           o)
     #ifdef __PPC__
@@ -2726,55 +3251,60 @@ struct kernel_statfs {
       LSS_SC_BODY(4, int, 8, d, type, protocol, sv);
     }
   #endif
   #if defined(__ARM_EABI__)
     LSS_INLINE _syscall3(ssize_t, recvmsg, int, s, struct kernel_msghdr*, msg,
                          int, flags)
     LSS_INLINE _syscall3(ssize_t, sendmsg, int, s, const struct kernel_msghdr*,
                          msg, int, flags)
-    LSS_INLINE _syscall6(ssize_t, sendto, int, s, const void*, buf, size_t, len,
-                         int, falgs, const struct kernel_sockaddr*, to,
+    LSS_INLINE _syscall6(ssize_t, sendto, int, s, const void*, buf, size_t,len,
+                         int, flags, const struct kernel_sockaddr*, to,
                          unsigned int, tolen)
     LSS_INLINE _syscall2(int, shutdown, int, s, int, how)
     LSS_INLINE _syscall3(int, socket, int, domain, int, type, int, protocol)
-    LSS_INLINE _syscall4(int, socketpair, int, d, int, type, int, protocol, 
+    LSS_INLINE _syscall4(int, socketpair, int, d, int, type, int, protocol,
                          int*, sv)
   #endif
-  #if defined(__i386__) || defined(__ARM_ARCH_3__) ||                      \
+  #if defined(__i386__) || defined(__ARM_ARCH_3__) ||                         \
       (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
     #define __NR__socketcall  __NR_socketcall
     LSS_INLINE _syscall2(int,      _socketcall,    int,   c,
                          va_list,                  a)
     LSS_INLINE int LSS_NAME(socketcall)(int op, ...) {
       int rc;
       va_list ap;
       va_start(ap, op);
       rc = LSS_NAME(_socketcall)(op, ap);
       va_end(ap);
       return rc;
     }
+
     LSS_INLINE ssize_t LSS_NAME(recvmsg)(int s,struct kernel_msghdr *msg,
                                          int flags){
       return (ssize_t)LSS_NAME(socketcall)(17, s, msg, flags);
     }
+
     LSS_INLINE ssize_t LSS_NAME(sendmsg)(int s,
                                          const struct kernel_msghdr *msg,
                                          int flags) {
       return (ssize_t)LSS_NAME(socketcall)(16, s, msg, flags);
     }
+
     LSS_INLINE ssize_t LSS_NAME(sendto)(int s, const void *buf, size_t len,
                                         int flags,
                                         const struct kernel_sockaddr *to,
                                         unsigned int tolen) {
       return (ssize_t)LSS_NAME(socketcall)(11, s, buf, len, flags, to, tolen);
     }
+
     LSS_INLINE int LSS_NAME(shutdown)(int s, int how) {
       return LSS_NAME(socketcall)(13, s, how);
     }
+
     LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) {
       return LSS_NAME(socketcall)(1, domain, type, protocol);
     }
 
     LSS_INLINE int LSS_NAME(socketpair)(int d, int type, int protocol,
                                         int sv[2]) {
       return LSS_NAME(socketcall)(8, d, type, protocol, sv);
     }
@@ -2859,22 +3389,29 @@ struct kernel_statfs {
   }
 
   LSS_INLINE int LSS_NAME(ptrace_detach)(pid_t pid) {
     /* PTRACE_DETACH can sometimes forget to wake up the tracee and it
      * then sends job control signals to the real parent, rather than to
      * the tracer. We reduce the risk of this happening by starting a
      * whole new time slice, and then quickly sending a SIGCONT signal
      * right after detaching from the tracee.
+     *
+     * We use tkill to ensure that we only issue a wakeup for the thread being
+     * detached.  Large multi threaded apps can take a long time in the kernel
+     * processing SIGCONT.
      */
     int rc, err;
     LSS_NAME(sched_yield)();
     rc = LSS_NAME(ptrace)(PTRACE_DETACH, pid, (void *)0, (void *)0);
     err = LSS_ERRNO;
-    LSS_NAME(kill)(pid, SIGCONT);
+    LSS_NAME(tkill)(pid, SIGCONT);
+    /* Old systems don't have tkill */
+    if (LSS_ERRNO == ENOSYS)
+      LSS_NAME(kill)(pid, SIGCONT);
     LSS_ERRNO = err;
     return rc;
   }
 
   LSS_INLINE int LSS_NAME(raise)(int sig) {
     return LSS_NAME(kill)(LSS_NAME(getpid)(), sig);
   }
 
@@ -2893,23 +3430,28 @@ struct kernel_statfs {
 #else
         return LSS_NAME(getrlimit)(RLIMIT_NOFILE, &limit) < 0
             ? 8192 : limit.rlim_cur;
 #endif
       }
       case _SC_PAGESIZE:
         return __getpagesize();
       default:
-        errno = ENOSYS;
+        LSS_ERRNO = ENOSYS;
         return -1;
     }
   }
   #if defined(__x86_64__) ||                                                  \
      (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI64)
-    /* pread64() and pwrite64() do not exist on 64-bit systems...            */
+    LSS_INLINE _syscall4(ssize_t, pread64,        int,         f,
+                         void *,         b, size_t,   c,
+                         loff_t,         o)
+    LSS_INLINE _syscall4(ssize_t, pwrite64,       int,         f,
+                         const void *,   b, size_t,   c,
+                         loff_t,         o)
     LSS_INLINE _syscall3(int,     readahead,      int,         f,
                          loff_t,         o, unsigned, c)
   #else
     #define __NR__pread64   __NR_pread64
     #define __NR__pwrite64  __NR_pwrite64
     #define __NR__readahead __NR_readahead
     LSS_INLINE _syscall5(ssize_t, _pread64,        int,         f,
                          void *,         b, size_t, c, unsigned, o1,