Merge "Update timezone data to 2016b" into nyc-dev
diff --git a/libc/Android.bp b/libc/Android.bp
index ca926d6..4cae16c 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -385,6 +385,7 @@
     cflags: [
         "-Wno-sign-compare",
         "-Wno-uninitialized",
+        "-Wno-unused-parameter",
         "-DPOSIX_MISTAKE",
         "-include netbsd-compat.h",
     ],
diff --git a/libc/arch-x86/bionic/setjmp.S b/libc/arch-x86/bionic/setjmp.S
index 86e6e3c..efb6459 100644
--- a/libc/arch-x86/bionic/setjmp.S
+++ b/libc/arch-x86/bionic/setjmp.S
@@ -32,6 +32,21 @@
 
 #include <private/bionic_asm.h>
 
+// The internal structure of a jmp_buf is totally private.
+// Current layout (changes from release to release):
+//
+// word   name            description
+// 0      edx             registers
+// 1      ebx
+// 2      esp
+// 3      ebp
+// 4      esi
+// 5      edi
+// 6      sigmask         signal mask (not used with _setjmp / _longjmp)
+// 7      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
+// 8      checksum        checksum of the core registers, to give better error messages.
+// 9      reserved
+
 #define _JB_EDX 0
 #define _JB_EBX 1
 #define _JB_ESP 2
@@ -40,6 +55,7 @@
 #define _JB_EDI 5
 #define _JB_SIGMASK 6
 #define _JB_SIGFLAG 7
+#define _JB_CHECKSUM 8
 
 .macro m_mangle_registers reg
   xorl \reg,%edx
@@ -54,6 +70,13 @@
   m_mangle_registers \reg
 .endm
 
+.macro m_calculate_checksum dst, src
+  movl $0, \dst
+  .irp i,0,1,2,3,4,5
+    xorl (\i*4)(\src), \dst
+  .endr
+.endm
+
 ENTRY(setjmp)
   movl 4(%esp),%ecx
   mov $1,%eax
@@ -111,13 +134,22 @@
   movl %edi,(_JB_EDI * 4)(%ecx)
   m_unmangle_registers %eax
 
+  m_calculate_checksum %eax, %ecx
+  movl %eax, (_JB_CHECKSUM * 4)(%ecx)
+
   xorl %eax,%eax
   ret
 END(sigsetjmp)
 
 ENTRY(siglongjmp)
-  // Do we have a signal mask to restore?
   movl 4(%esp),%edx
+
+  // Check the checksum before doing anything.
+  m_calculate_checksum %eax, %edx
+  xorl (_JB_CHECKSUM * 4)(%edx), %eax
+  jnz 3f
+
+  // Do we have a signal mask to restore?
   movl (_JB_SIGFLAG * 4)(%edx), %eax
   testl $1,%eax
   jz 1f
@@ -165,6 +197,11 @@
 2:
   movl %ecx,0(%esp)
   ret
+
+3:
+  PIC_PROLOGUE
+  pushl (_JB_SIGMASK * 4)(%edx)
+  call PIC_PLT(__bionic_setjmp_checksum_mismatch)
 END(siglongjmp)
 
 ALIAS_SYMBOL(longjmp, siglongjmp)
diff --git a/libc/arch-x86/bionic/syscall.S b/libc/arch-x86/bionic/syscall.S
index 2a15102..12402ac 100644
--- a/libc/arch-x86/bionic/syscall.S
+++ b/libc/arch-x86/bionic/syscall.S
@@ -27,18 +27,25 @@
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
 
+    # Get and save the system call entry address.
+    call    __kernel_syscall
+    push    %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     # Load all the arguments from the calling frame.
     # (Not all will be valid, depending on the syscall.)
-    mov     20(%esp),%eax
-    mov     24(%esp),%ebx
-    mov     28(%esp),%ecx
-    mov     32(%esp),%edx
-    mov     36(%esp),%esi
-    mov     40(%esp),%edi
-    mov     44(%esp),%ebp
+    mov     24(%esp),%eax
+    mov     28(%esp),%ebx
+    mov     32(%esp),%ecx
+    mov     36(%esp),%edx
+    mov     40(%esp),%esi
+    mov     44(%esp),%edi
+    mov     48(%esp),%ebp
 
     # Make the system call.
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
 
     # Error?
     cmpl    $-MAX_ERRNO, %eax
diff --git a/libc/arch-x86/syscalls/___clock_nanosleep.S b/libc/arch-x86/syscalls/___clock_nanosleep.S
index 088a92e..6998749 100644
--- a/libc/arch-x86/syscalls/___clock_nanosleep.S
+++ b/libc/arch-x86/syscalls/___clock_nanosleep.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_clock_nanosleep, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___close.S b/libc/arch-x86/syscalls/___close.S
index 796944b..b9ebdaa 100644
--- a/libc/arch-x86/syscalls/___close.S
+++ b/libc/arch-x86/syscalls/___close.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_close, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___faccessat.S b/libc/arch-x86/syscalls/___faccessat.S
index 361a6ea..b92b03d 100644
--- a/libc/arch-x86/syscalls/___faccessat.S
+++ b/libc/arch-x86/syscalls/___faccessat.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_faccessat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___fchmod.S b/libc/arch-x86/syscalls/___fchmod.S
index 119a695..92e864c 100644
--- a/libc/arch-x86/syscalls/___fchmod.S
+++ b/libc/arch-x86/syscalls/___fchmod.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_fchmod, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___fchmodat.S b/libc/arch-x86/syscalls/___fchmodat.S
index b15bb64..81edf96 100644
--- a/libc/arch-x86/syscalls/___fchmodat.S
+++ b/libc/arch-x86/syscalls/___fchmodat.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_fchmodat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___fgetxattr.S b/libc/arch-x86/syscalls/___fgetxattr.S
index 2891511..712728d 100644
--- a/libc/arch-x86/syscalls/___fgetxattr.S
+++ b/libc/arch-x86/syscalls/___fgetxattr.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_fgetxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___flistxattr.S b/libc/arch-x86/syscalls/___flistxattr.S
index a67967b..a22ef35 100644
--- a/libc/arch-x86/syscalls/___flistxattr.S
+++ b/libc/arch-x86/syscalls/___flistxattr.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_flistxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___fsetxattr.S b/libc/arch-x86/syscalls/___fsetxattr.S
index 287dafc..b90c972 100644
--- a/libc/arch-x86/syscalls/___fsetxattr.S
+++ b/libc/arch-x86/syscalls/___fsetxattr.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_fsetxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___mremap.S b/libc/arch-x86/syscalls/___mremap.S
index e5e9c54..9d9bfcb 100644
--- a/libc/arch-x86/syscalls/___mremap.S
+++ b/libc/arch-x86/syscalls/___mremap.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_mremap, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/___rt_sigqueueinfo.S b/libc/arch-x86/syscalls/___rt_sigqueueinfo.S
index 97d167f..e299707 100644
--- a/libc/arch-x86/syscalls/___rt_sigqueueinfo.S
+++ b/libc/arch-x86/syscalls/___rt_sigqueueinfo.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_rt_sigqueueinfo, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__accept4.S b/libc/arch-x86/syscalls/__accept4.S
index 7b16dd4..112a8a7 100644
--- a/libc/arch-x86/syscalls/__accept4.S
+++ b/libc/arch-x86/syscalls/__accept4.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $18, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__brk.S b/libc/arch-x86/syscalls/__brk.S
index 22acdad..bf2f1d2 100644
--- a/libc/arch-x86/syscalls/__brk.S
+++ b/libc/arch-x86/syscalls/__brk.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_brk, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__clock_gettime.S b/libc/arch-x86/syscalls/__clock_gettime.S
index 61eadc8..0c0c1c4 100644
--- a/libc/arch-x86/syscalls/__clock_gettime.S
+++ b/libc/arch-x86/syscalls/__clock_gettime.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_clock_gettime, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__connect.S b/libc/arch-x86/syscalls/__connect.S
index 475d452..5ea160c 100644
--- a/libc/arch-x86/syscalls/__connect.S
+++ b/libc/arch-x86/syscalls/__connect.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $3, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__epoll_pwait.S b/libc/arch-x86/syscalls/__epoll_pwait.S
index 171caa5..3750760 100644
--- a/libc/arch-x86/syscalls/__epoll_pwait.S
+++ b/libc/arch-x86/syscalls/__epoll_pwait.S
@@ -21,14 +21,22 @@
     pushl   %ebp
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
-    mov     28(%esp), %ebx
-    mov     32(%esp), %ecx
-    mov     36(%esp), %edx
-    mov     40(%esp), %esi
-    mov     44(%esp), %edi
-    mov     48(%esp), %ebp
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     32(%esp), %ebx
+    mov     36(%esp), %ecx
+    mov     40(%esp), %edx
+    mov     44(%esp), %esi
+    mov     48(%esp), %edi
+    mov     52(%esp), %ebp
     movl    $__NR_epoll_pwait, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__exit.S b/libc/arch-x86/syscalls/__exit.S
index 8cf3663..841c8cf 100644
--- a/libc/arch-x86/syscalls/__exit.S
+++ b/libc/arch-x86/syscalls/__exit.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_exit, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__fadvise64.S b/libc/arch-x86/syscalls/__fadvise64.S
index 6e4298a..d580a61 100644
--- a/libc/arch-x86/syscalls/__fadvise64.S
+++ b/libc/arch-x86/syscalls/__fadvise64.S
@@ -21,14 +21,22 @@
     pushl   %ebp
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
-    mov     28(%esp), %ebx
-    mov     32(%esp), %ecx
-    mov     36(%esp), %edx
-    mov     40(%esp), %esi
-    mov     44(%esp), %edi
-    mov     48(%esp), %ebp
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     32(%esp), %ebx
+    mov     36(%esp), %ecx
+    mov     40(%esp), %edx
+    mov     44(%esp), %esi
+    mov     48(%esp), %edi
+    mov     52(%esp), %ebp
     movl    $__NR_fadvise64_64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__fcntl64.S b/libc/arch-x86/syscalls/__fcntl64.S
index d900a52..c886411 100644
--- a/libc/arch-x86/syscalls/__fcntl64.S
+++ b/libc/arch-x86/syscalls/__fcntl64.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_fcntl64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__fstatfs64.S b/libc/arch-x86/syscalls/__fstatfs64.S
index 9b44743..2c97435 100644
--- a/libc/arch-x86/syscalls/__fstatfs64.S
+++ b/libc/arch-x86/syscalls/__fstatfs64.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_fstatfs64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__getcpu.S b/libc/arch-x86/syscalls/__getcpu.S
index bb4c41f..fde7306 100644
--- a/libc/arch-x86/syscalls/__getcpu.S
+++ b/libc/arch-x86/syscalls/__getcpu.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_getcpu, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__getcwd.S b/libc/arch-x86/syscalls/__getcwd.S
index 8decd99..dc0bded 100644
--- a/libc/arch-x86/syscalls/__getcwd.S
+++ b/libc/arch-x86/syscalls/__getcwd.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_getcwd, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__getdents64.S b/libc/arch-x86/syscalls/__getdents64.S
index 5190a68..4228da2 100644
--- a/libc/arch-x86/syscalls/__getdents64.S
+++ b/libc/arch-x86/syscalls/__getdents64.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_getdents64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__getpid.S b/libc/arch-x86/syscalls/__getpid.S
index 197202c..aa5d343 100644
--- a/libc/arch-x86/syscalls/__getpid.S
+++ b/libc/arch-x86/syscalls/__getpid.S
@@ -3,8 +3,16 @@
 #include <private/bionic_asm.h>
 
 ENTRY(__getpid)
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     movl    $__NR_getpid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__getpriority.S b/libc/arch-x86/syscalls/__getpriority.S
index dd5591f..cf2fbc3 100644
--- a/libc/arch-x86/syscalls/__getpriority.S
+++ b/libc/arch-x86/syscalls/__getpriority.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_getpriority, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__gettimeofday.S b/libc/arch-x86/syscalls/__gettimeofday.S
index 90f3f91..4e24cdd 100644
--- a/libc/arch-x86/syscalls/__gettimeofday.S
+++ b/libc/arch-x86/syscalls/__gettimeofday.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_gettimeofday, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__ioctl.S b/libc/arch-x86/syscalls/__ioctl.S
index b6ee9f2..2189638 100644
--- a/libc/arch-x86/syscalls/__ioctl.S
+++ b/libc/arch-x86/syscalls/__ioctl.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_ioctl, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__llseek.S b/libc/arch-x86/syscalls/__llseek.S
index 5cc907a..9213891 100644
--- a/libc/arch-x86/syscalls/__llseek.S
+++ b/libc/arch-x86/syscalls/__llseek.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR__llseek, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__mmap2.S b/libc/arch-x86/syscalls/__mmap2.S
index 08314c8..0904a3d 100644
--- a/libc/arch-x86/syscalls/__mmap2.S
+++ b/libc/arch-x86/syscalls/__mmap2.S
@@ -21,14 +21,22 @@
     pushl   %ebp
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
-    mov     28(%esp), %ebx
-    mov     32(%esp), %ecx
-    mov     36(%esp), %edx
-    mov     40(%esp), %esi
-    mov     44(%esp), %edi
-    mov     48(%esp), %ebp
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     32(%esp), %ebx
+    mov     36(%esp), %ecx
+    mov     40(%esp), %edx
+    mov     44(%esp), %esi
+    mov     48(%esp), %edi
+    mov     52(%esp), %ebp
     movl    $__NR_mmap2, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__openat.S b/libc/arch-x86/syscalls/__openat.S
index 4c11709..03c03bd 100644
--- a/libc/arch-x86/syscalls/__openat.S
+++ b/libc/arch-x86/syscalls/__openat.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_openat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__ppoll.S b/libc/arch-x86/syscalls/__ppoll.S
index 2a1f76e..1a55b03 100644
--- a/libc/arch-x86/syscalls/__ppoll.S
+++ b/libc/arch-x86/syscalls/__ppoll.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_ppoll, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__preadv64.S b/libc/arch-x86/syscalls/__preadv64.S
index 3ce4fc3..5db22a3 100644
--- a/libc/arch-x86/syscalls/__preadv64.S
+++ b/libc/arch-x86/syscalls/__preadv64.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_preadv, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__pselect6.S b/libc/arch-x86/syscalls/__pselect6.S
index 8ff102a..18327fd 100644
--- a/libc/arch-x86/syscalls/__pselect6.S
+++ b/libc/arch-x86/syscalls/__pselect6.S
@@ -21,14 +21,22 @@
     pushl   %ebp
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
-    mov     28(%esp), %ebx
-    mov     32(%esp), %ecx
-    mov     36(%esp), %edx
-    mov     40(%esp), %esi
-    mov     44(%esp), %edi
-    mov     48(%esp), %ebp
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     32(%esp), %ebx
+    mov     36(%esp), %ecx
+    mov     40(%esp), %edx
+    mov     44(%esp), %esi
+    mov     48(%esp), %edi
+    mov     52(%esp), %ebp
     movl    $__NR_pselect6, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__ptrace.S b/libc/arch-x86/syscalls/__ptrace.S
index d982cec..a522e95 100644
--- a/libc/arch-x86/syscalls/__ptrace.S
+++ b/libc/arch-x86/syscalls/__ptrace.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_ptrace, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__pwritev64.S b/libc/arch-x86/syscalls/__pwritev64.S
index 2ce5b0e..19f1865 100644
--- a/libc/arch-x86/syscalls/__pwritev64.S
+++ b/libc/arch-x86/syscalls/__pwritev64.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_pwritev, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__reboot.S b/libc/arch-x86/syscalls/__reboot.S
index 3d169bf..711a4e6 100644
--- a/libc/arch-x86/syscalls/__reboot.S
+++ b/libc/arch-x86/syscalls/__reboot.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_reboot, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__rt_sigaction.S b/libc/arch-x86/syscalls/__rt_sigaction.S
index 59c3882..ebc431d 100644
--- a/libc/arch-x86/syscalls/__rt_sigaction.S
+++ b/libc/arch-x86/syscalls/__rt_sigaction.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_rt_sigaction, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__rt_sigpending.S b/libc/arch-x86/syscalls/__rt_sigpending.S
index 9c6a106..ecf2945 100644
--- a/libc/arch-x86/syscalls/__rt_sigpending.S
+++ b/libc/arch-x86/syscalls/__rt_sigpending.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_rt_sigpending, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__rt_sigprocmask.S b/libc/arch-x86/syscalls/__rt_sigprocmask.S
index 9b1532f..cdd0f10 100644
--- a/libc/arch-x86/syscalls/__rt_sigprocmask.S
+++ b/libc/arch-x86/syscalls/__rt_sigprocmask.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_rt_sigprocmask, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__rt_sigsuspend.S b/libc/arch-x86/syscalls/__rt_sigsuspend.S
index b05acd8..ef96949 100644
--- a/libc/arch-x86/syscalls/__rt_sigsuspend.S
+++ b/libc/arch-x86/syscalls/__rt_sigsuspend.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_rt_sigsuspend, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__rt_sigtimedwait.S b/libc/arch-x86/syscalls/__rt_sigtimedwait.S
index 14cb70f..8205221 100644
--- a/libc/arch-x86/syscalls/__rt_sigtimedwait.S
+++ b/libc/arch-x86/syscalls/__rt_sigtimedwait.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_rt_sigtimedwait, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__sched_getaffinity.S b/libc/arch-x86/syscalls/__sched_getaffinity.S
index 0b0a970..ba658af 100644
--- a/libc/arch-x86/syscalls/__sched_getaffinity.S
+++ b/libc/arch-x86/syscalls/__sched_getaffinity.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_sched_getaffinity, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__set_thread_area.S b/libc/arch-x86/syscalls/__set_thread_area.S
index 8cd6880..7fc04bd 100644
--- a/libc/arch-x86/syscalls/__set_thread_area.S
+++ b/libc/arch-x86/syscalls/__set_thread_area.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_set_thread_area, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__set_tid_address.S b/libc/arch-x86/syscalls/__set_tid_address.S
index 08acce9..4301156 100644
--- a/libc/arch-x86/syscalls/__set_tid_address.S
+++ b/libc/arch-x86/syscalls/__set_tid_address.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_set_tid_address, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__sigaction.S b/libc/arch-x86/syscalls/__sigaction.S
index 0238247..6b2b7f3 100644
--- a/libc/arch-x86/syscalls/__sigaction.S
+++ b/libc/arch-x86/syscalls/__sigaction.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_sigaction, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__signalfd4.S b/libc/arch-x86/syscalls/__signalfd4.S
index 02ddc73..ea817cf 100644
--- a/libc/arch-x86/syscalls/__signalfd4.S
+++ b/libc/arch-x86/syscalls/__signalfd4.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_signalfd4, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__socket.S b/libc/arch-x86/syscalls/__socket.S
index 75952ee..06d1f1f 100644
--- a/libc/arch-x86/syscalls/__socket.S
+++ b/libc/arch-x86/syscalls/__socket.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $1, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__statfs64.S b/libc/arch-x86/syscalls/__statfs64.S
index b9bccb0..79e1f4b 100644
--- a/libc/arch-x86/syscalls/__statfs64.S
+++ b/libc/arch-x86/syscalls/__statfs64.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_statfs64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__timer_create.S b/libc/arch-x86/syscalls/__timer_create.S
index b22f408..4e16b1c 100644
--- a/libc/arch-x86/syscalls/__timer_create.S
+++ b/libc/arch-x86/syscalls/__timer_create.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_timer_create, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__timer_delete.S b/libc/arch-x86/syscalls/__timer_delete.S
index d77ae3e..fea422e 100644
--- a/libc/arch-x86/syscalls/__timer_delete.S
+++ b/libc/arch-x86/syscalls/__timer_delete.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_timer_delete, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__timer_getoverrun.S b/libc/arch-x86/syscalls/__timer_getoverrun.S
index f21b08f..e921073 100644
--- a/libc/arch-x86/syscalls/__timer_getoverrun.S
+++ b/libc/arch-x86/syscalls/__timer_getoverrun.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_timer_getoverrun, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__timer_gettime.S b/libc/arch-x86/syscalls/__timer_gettime.S
index 73c8539..4e20356 100644
--- a/libc/arch-x86/syscalls/__timer_gettime.S
+++ b/libc/arch-x86/syscalls/__timer_gettime.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_timer_gettime, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__timer_settime.S b/libc/arch-x86/syscalls/__timer_settime.S
index 1a6a8ec..9b8af34 100644
--- a/libc/arch-x86/syscalls/__timer_settime.S
+++ b/libc/arch-x86/syscalls/__timer_settime.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_timer_settime, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/__waitid.S b/libc/arch-x86/syscalls/__waitid.S
index 2061abc..f134b42 100644
--- a/libc/arch-x86/syscalls/__waitid.S
+++ b/libc/arch-x86/syscalls/__waitid.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_waitid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/_exit.S b/libc/arch-x86/syscalls/_exit.S
index 9945b35..1e89261 100644
--- a/libc/arch-x86/syscalls/_exit.S
+++ b/libc/arch-x86/syscalls/_exit.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_exit_group, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/acct.S b/libc/arch-x86/syscalls/acct.S
index d831771..48c4c5c 100644
--- a/libc/arch-x86/syscalls/acct.S
+++ b/libc/arch-x86/syscalls/acct.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_acct, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/adjtimex.S b/libc/arch-x86/syscalls/adjtimex.S
index 2a91f90..1b0d8b1 100644
--- a/libc/arch-x86/syscalls/adjtimex.S
+++ b/libc/arch-x86/syscalls/adjtimex.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_adjtimex, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/bind.S b/libc/arch-x86/syscalls/bind.S
index 9ef817e..c1f84da 100644
--- a/libc/arch-x86/syscalls/bind.S
+++ b/libc/arch-x86/syscalls/bind.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $2, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/capget.S b/libc/arch-x86/syscalls/capget.S
index 81c24e8..fafde37 100644
--- a/libc/arch-x86/syscalls/capget.S
+++ b/libc/arch-x86/syscalls/capget.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_capget, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/capset.S b/libc/arch-x86/syscalls/capset.S
index 4e311e9..28e5338 100644
--- a/libc/arch-x86/syscalls/capset.S
+++ b/libc/arch-x86/syscalls/capset.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_capset, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/chdir.S b/libc/arch-x86/syscalls/chdir.S
index 2226a1a..4b639eb 100644
--- a/libc/arch-x86/syscalls/chdir.S
+++ b/libc/arch-x86/syscalls/chdir.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_chdir, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/chroot.S b/libc/arch-x86/syscalls/chroot.S
index 95ed0b5..8887f86 100644
--- a/libc/arch-x86/syscalls/chroot.S
+++ b/libc/arch-x86/syscalls/chroot.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_chroot, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/clock_adjtime.S b/libc/arch-x86/syscalls/clock_adjtime.S
index b6e0ac4..4ccf1a6 100644
--- a/libc/arch-x86/syscalls/clock_adjtime.S
+++ b/libc/arch-x86/syscalls/clock_adjtime.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_clock_adjtime, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/clock_getres.S b/libc/arch-x86/syscalls/clock_getres.S
index 9501799..9466e08 100644
--- a/libc/arch-x86/syscalls/clock_getres.S
+++ b/libc/arch-x86/syscalls/clock_getres.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_clock_getres, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/clock_settime.S b/libc/arch-x86/syscalls/clock_settime.S
index 96fafed..62dc021 100644
--- a/libc/arch-x86/syscalls/clock_settime.S
+++ b/libc/arch-x86/syscalls/clock_settime.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_clock_settime, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/delete_module.S b/libc/arch-x86/syscalls/delete_module.S
index 58b8d6b..b0c8ff9 100644
--- a/libc/arch-x86/syscalls/delete_module.S
+++ b/libc/arch-x86/syscalls/delete_module.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_delete_module, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/dup.S b/libc/arch-x86/syscalls/dup.S
index 0fd9cce..637cfae 100644
--- a/libc/arch-x86/syscalls/dup.S
+++ b/libc/arch-x86/syscalls/dup.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_dup, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/dup3.S b/libc/arch-x86/syscalls/dup3.S
index 8348660..4d08eab 100644
--- a/libc/arch-x86/syscalls/dup3.S
+++ b/libc/arch-x86/syscalls/dup3.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_dup3, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/epoll_create1.S b/libc/arch-x86/syscalls/epoll_create1.S
index 0fcd09c..93d1c00 100644
--- a/libc/arch-x86/syscalls/epoll_create1.S
+++ b/libc/arch-x86/syscalls/epoll_create1.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_epoll_create1, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/epoll_ctl.S b/libc/arch-x86/syscalls/epoll_ctl.S
index 092c1e0..a2d8d27 100644
--- a/libc/arch-x86/syscalls/epoll_ctl.S
+++ b/libc/arch-x86/syscalls/epoll_ctl.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_epoll_ctl, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/eventfd.S b/libc/arch-x86/syscalls/eventfd.S
index cc165e5..89f9442 100644
--- a/libc/arch-x86/syscalls/eventfd.S
+++ b/libc/arch-x86/syscalls/eventfd.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_eventfd2, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/execve.S b/libc/arch-x86/syscalls/execve.S
index e1c0253..7695635 100644
--- a/libc/arch-x86/syscalls/execve.S
+++ b/libc/arch-x86/syscalls/execve.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_execve, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fallocate64.S b/libc/arch-x86/syscalls/fallocate64.S
index e2a7c3e..eabc642 100644
--- a/libc/arch-x86/syscalls/fallocate64.S
+++ b/libc/arch-x86/syscalls/fallocate64.S
@@ -21,14 +21,22 @@
     pushl   %ebp
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
-    mov     28(%esp), %ebx
-    mov     32(%esp), %ecx
-    mov     36(%esp), %edx
-    mov     40(%esp), %esi
-    mov     44(%esp), %edi
-    mov     48(%esp), %ebp
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     32(%esp), %ebx
+    mov     36(%esp), %ecx
+    mov     40(%esp), %edx
+    mov     44(%esp), %esi
+    mov     48(%esp), %edi
+    mov     52(%esp), %ebp
     movl    $__NR_fallocate, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fchdir.S b/libc/arch-x86/syscalls/fchdir.S
index c40c2c1..5701644 100644
--- a/libc/arch-x86/syscalls/fchdir.S
+++ b/libc/arch-x86/syscalls/fchdir.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_fchdir, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fchown.S b/libc/arch-x86/syscalls/fchown.S
index 1a4f749..0d41389 100644
--- a/libc/arch-x86/syscalls/fchown.S
+++ b/libc/arch-x86/syscalls/fchown.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_fchown32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fchownat.S b/libc/arch-x86/syscalls/fchownat.S
index c2b358e..56b7777 100644
--- a/libc/arch-x86/syscalls/fchownat.S
+++ b/libc/arch-x86/syscalls/fchownat.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_fchownat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fdatasync.S b/libc/arch-x86/syscalls/fdatasync.S
index debd4e3..6ee9e15 100644
--- a/libc/arch-x86/syscalls/fdatasync.S
+++ b/libc/arch-x86/syscalls/fdatasync.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_fdatasync, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/flock.S b/libc/arch-x86/syscalls/flock.S
index 0fc76a8..b65543d 100644
--- a/libc/arch-x86/syscalls/flock.S
+++ b/libc/arch-x86/syscalls/flock.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_flock, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fremovexattr.S b/libc/arch-x86/syscalls/fremovexattr.S
index 2053a9a..3511d5d 100644
--- a/libc/arch-x86/syscalls/fremovexattr.S
+++ b/libc/arch-x86/syscalls/fremovexattr.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_fremovexattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fstat64.S b/libc/arch-x86/syscalls/fstat64.S
index ba385a4..16eca69 100644
--- a/libc/arch-x86/syscalls/fstat64.S
+++ b/libc/arch-x86/syscalls/fstat64.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_fstat64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fstatat64.S b/libc/arch-x86/syscalls/fstatat64.S
index 90e87b6..402cf60 100644
--- a/libc/arch-x86/syscalls/fstatat64.S
+++ b/libc/arch-x86/syscalls/fstatat64.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_fstatat64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/fsync.S b/libc/arch-x86/syscalls/fsync.S
index b19a3ab..53aeee6 100644
--- a/libc/arch-x86/syscalls/fsync.S
+++ b/libc/arch-x86/syscalls/fsync.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_fsync, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/ftruncate64.S b/libc/arch-x86/syscalls/ftruncate64.S
index 7233447..2fa792f 100644
--- a/libc/arch-x86/syscalls/ftruncate64.S
+++ b/libc/arch-x86/syscalls/ftruncate64.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_ftruncate64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getegid.S b/libc/arch-x86/syscalls/getegid.S
index 729b7ad..cb1921e 100644
--- a/libc/arch-x86/syscalls/getegid.S
+++ b/libc/arch-x86/syscalls/getegid.S
@@ -3,8 +3,16 @@
 #include <private/bionic_asm.h>
 
 ENTRY(getegid)
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     movl    $__NR_getegid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/geteuid.S b/libc/arch-x86/syscalls/geteuid.S
index dcc76b1..c08d3ae 100644
--- a/libc/arch-x86/syscalls/geteuid.S
+++ b/libc/arch-x86/syscalls/geteuid.S
@@ -3,8 +3,16 @@
 #include <private/bionic_asm.h>
 
 ENTRY(geteuid)
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     movl    $__NR_geteuid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getgid.S b/libc/arch-x86/syscalls/getgid.S
index b36a2c9..9189ae9 100644
--- a/libc/arch-x86/syscalls/getgid.S
+++ b/libc/arch-x86/syscalls/getgid.S
@@ -3,8 +3,16 @@
 #include <private/bionic_asm.h>
 
 ENTRY(getgid)
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     movl    $__NR_getgid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getgroups.S b/libc/arch-x86/syscalls/getgroups.S
index 0a5de35..8737d51 100644
--- a/libc/arch-x86/syscalls/getgroups.S
+++ b/libc/arch-x86/syscalls/getgroups.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_getgroups32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getitimer.S b/libc/arch-x86/syscalls/getitimer.S
index a0cb761..e088114 100644
--- a/libc/arch-x86/syscalls/getitimer.S
+++ b/libc/arch-x86/syscalls/getitimer.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_getitimer, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getpeername.S b/libc/arch-x86/syscalls/getpeername.S
index 6773e6a..40bb814 100644
--- a/libc/arch-x86/syscalls/getpeername.S
+++ b/libc/arch-x86/syscalls/getpeername.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $7, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getpgid.S b/libc/arch-x86/syscalls/getpgid.S
index f702cfd..9d362e8 100644
--- a/libc/arch-x86/syscalls/getpgid.S
+++ b/libc/arch-x86/syscalls/getpgid.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_getpgid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getppid.S b/libc/arch-x86/syscalls/getppid.S
index edbe384..afb40a1 100644
--- a/libc/arch-x86/syscalls/getppid.S
+++ b/libc/arch-x86/syscalls/getppid.S
@@ -3,8 +3,16 @@
 #include <private/bionic_asm.h>
 
 ENTRY(getppid)
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     movl    $__NR_getppid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getresgid.S b/libc/arch-x86/syscalls/getresgid.S
index 9f1a9dd..131c101 100644
--- a/libc/arch-x86/syscalls/getresgid.S
+++ b/libc/arch-x86/syscalls/getresgid.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_getresgid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getresuid.S b/libc/arch-x86/syscalls/getresuid.S
index 61e1370..94a8767 100644
--- a/libc/arch-x86/syscalls/getresuid.S
+++ b/libc/arch-x86/syscalls/getresuid.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_getresuid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getrlimit.S b/libc/arch-x86/syscalls/getrlimit.S
index c3acff3..c686f7c 100644
--- a/libc/arch-x86/syscalls/getrlimit.S
+++ b/libc/arch-x86/syscalls/getrlimit.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_ugetrlimit, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getrusage.S b/libc/arch-x86/syscalls/getrusage.S
index 0d715cd..51d1df1 100644
--- a/libc/arch-x86/syscalls/getrusage.S
+++ b/libc/arch-x86/syscalls/getrusage.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_getrusage, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getsid.S b/libc/arch-x86/syscalls/getsid.S
index e142c05..a4568e6 100644
--- a/libc/arch-x86/syscalls/getsid.S
+++ b/libc/arch-x86/syscalls/getsid.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_getsid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getsockname.S b/libc/arch-x86/syscalls/getsockname.S
index 6050190..0fd5836 100644
--- a/libc/arch-x86/syscalls/getsockname.S
+++ b/libc/arch-x86/syscalls/getsockname.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $6, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getsockopt.S b/libc/arch-x86/syscalls/getsockopt.S
index aec40cf..fa6fccf 100644
--- a/libc/arch-x86/syscalls/getsockopt.S
+++ b/libc/arch-x86/syscalls/getsockopt.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $15, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getuid.S b/libc/arch-x86/syscalls/getuid.S
index cc62884..11cc0c6 100644
--- a/libc/arch-x86/syscalls/getuid.S
+++ b/libc/arch-x86/syscalls/getuid.S
@@ -3,8 +3,16 @@
 #include <private/bionic_asm.h>
 
 ENTRY(getuid)
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     movl    $__NR_getuid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/getxattr.S b/libc/arch-x86/syscalls/getxattr.S
index a2cf137..871362e 100644
--- a/libc/arch-x86/syscalls/getxattr.S
+++ b/libc/arch-x86/syscalls/getxattr.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_getxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/init_module.S b/libc/arch-x86/syscalls/init_module.S
index 1d0f111..0147eee 100644
--- a/libc/arch-x86/syscalls/init_module.S
+++ b/libc/arch-x86/syscalls/init_module.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_init_module, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/inotify_add_watch.S b/libc/arch-x86/syscalls/inotify_add_watch.S
index 8cadc6e..f196440 100644
--- a/libc/arch-x86/syscalls/inotify_add_watch.S
+++ b/libc/arch-x86/syscalls/inotify_add_watch.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_inotify_add_watch, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/inotify_init1.S b/libc/arch-x86/syscalls/inotify_init1.S
index 23671e0..7f0dcfb 100644
--- a/libc/arch-x86/syscalls/inotify_init1.S
+++ b/libc/arch-x86/syscalls/inotify_init1.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_inotify_init1, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/inotify_rm_watch.S b/libc/arch-x86/syscalls/inotify_rm_watch.S
index c246c00..595e053 100644
--- a/libc/arch-x86/syscalls/inotify_rm_watch.S
+++ b/libc/arch-x86/syscalls/inotify_rm_watch.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_inotify_rm_watch, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/kill.S b/libc/arch-x86/syscalls/kill.S
index edc9cde..4ee56e6 100644
--- a/libc/arch-x86/syscalls/kill.S
+++ b/libc/arch-x86/syscalls/kill.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_kill, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/klogctl.S b/libc/arch-x86/syscalls/klogctl.S
index 5de9a31e..3d07942 100644
--- a/libc/arch-x86/syscalls/klogctl.S
+++ b/libc/arch-x86/syscalls/klogctl.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_syslog, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/lgetxattr.S b/libc/arch-x86/syscalls/lgetxattr.S
index 55697a0..659b088 100644
--- a/libc/arch-x86/syscalls/lgetxattr.S
+++ b/libc/arch-x86/syscalls/lgetxattr.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_lgetxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/linkat.S b/libc/arch-x86/syscalls/linkat.S
index 8b2646d..644172d 100644
--- a/libc/arch-x86/syscalls/linkat.S
+++ b/libc/arch-x86/syscalls/linkat.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_linkat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/listen.S b/libc/arch-x86/syscalls/listen.S
index 8ae4186..ce7c3a9 100644
--- a/libc/arch-x86/syscalls/listen.S
+++ b/libc/arch-x86/syscalls/listen.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $4, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/listxattr.S b/libc/arch-x86/syscalls/listxattr.S
index a73dc1a..2fe799e 100644
--- a/libc/arch-x86/syscalls/listxattr.S
+++ b/libc/arch-x86/syscalls/listxattr.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_listxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/llistxattr.S b/libc/arch-x86/syscalls/llistxattr.S
index 63d4489..666d87e 100644
--- a/libc/arch-x86/syscalls/llistxattr.S
+++ b/libc/arch-x86/syscalls/llistxattr.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_llistxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/lremovexattr.S b/libc/arch-x86/syscalls/lremovexattr.S
index 42c7e0f..bda772b 100644
--- a/libc/arch-x86/syscalls/lremovexattr.S
+++ b/libc/arch-x86/syscalls/lremovexattr.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_lremovexattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/lseek.S b/libc/arch-x86/syscalls/lseek.S
index bfe9e63..9142b5c 100644
--- a/libc/arch-x86/syscalls/lseek.S
+++ b/libc/arch-x86/syscalls/lseek.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_lseek, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/lsetxattr.S b/libc/arch-x86/syscalls/lsetxattr.S
index f36fc6a..fa977b3 100644
--- a/libc/arch-x86/syscalls/lsetxattr.S
+++ b/libc/arch-x86/syscalls/lsetxattr.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_lsetxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/madvise.S b/libc/arch-x86/syscalls/madvise.S
index b69f5d4..21f472e 100644
--- a/libc/arch-x86/syscalls/madvise.S
+++ b/libc/arch-x86/syscalls/madvise.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_madvise, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/mincore.S b/libc/arch-x86/syscalls/mincore.S
index 6d1df67..4179c9a 100644
--- a/libc/arch-x86/syscalls/mincore.S
+++ b/libc/arch-x86/syscalls/mincore.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_mincore, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/mkdirat.S b/libc/arch-x86/syscalls/mkdirat.S
index 5b6ae18..6a9d94c 100644
--- a/libc/arch-x86/syscalls/mkdirat.S
+++ b/libc/arch-x86/syscalls/mkdirat.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_mkdirat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/mknodat.S b/libc/arch-x86/syscalls/mknodat.S
index b19d972..a1fae7f 100644
--- a/libc/arch-x86/syscalls/mknodat.S
+++ b/libc/arch-x86/syscalls/mknodat.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_mknodat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/mlock.S b/libc/arch-x86/syscalls/mlock.S
index 517e5a5..1c57ac0 100644
--- a/libc/arch-x86/syscalls/mlock.S
+++ b/libc/arch-x86/syscalls/mlock.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_mlock, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/mlockall.S b/libc/arch-x86/syscalls/mlockall.S
index 756ca16..9f54de3 100644
--- a/libc/arch-x86/syscalls/mlockall.S
+++ b/libc/arch-x86/syscalls/mlockall.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_mlockall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/mount.S b/libc/arch-x86/syscalls/mount.S
index 0537528..4a9f91a 100644
--- a/libc/arch-x86/syscalls/mount.S
+++ b/libc/arch-x86/syscalls/mount.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_mount, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/mprotect.S b/libc/arch-x86/syscalls/mprotect.S
index 1ba186c..5eec550 100644
--- a/libc/arch-x86/syscalls/mprotect.S
+++ b/libc/arch-x86/syscalls/mprotect.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_mprotect, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/msync.S b/libc/arch-x86/syscalls/msync.S
index 81bd598..7754da6 100644
--- a/libc/arch-x86/syscalls/msync.S
+++ b/libc/arch-x86/syscalls/msync.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_msync, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/munlock.S b/libc/arch-x86/syscalls/munlock.S
index 67ca3fe..d2ae9f0 100644
--- a/libc/arch-x86/syscalls/munlock.S
+++ b/libc/arch-x86/syscalls/munlock.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_munlock, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/munlockall.S b/libc/arch-x86/syscalls/munlockall.S
index bf0bfa1..e709b8c 100644
--- a/libc/arch-x86/syscalls/munlockall.S
+++ b/libc/arch-x86/syscalls/munlockall.S
@@ -3,8 +3,16 @@
 #include <private/bionic_asm.h>
 
 ENTRY(munlockall)
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     movl    $__NR_munlockall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/munmap.S b/libc/arch-x86/syscalls/munmap.S
index 272cb52..7ddc5aa 100644
--- a/libc/arch-x86/syscalls/munmap.S
+++ b/libc/arch-x86/syscalls/munmap.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_munmap, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/nanosleep.S b/libc/arch-x86/syscalls/nanosleep.S
index 5c46a4a..580f5e1 100644
--- a/libc/arch-x86/syscalls/nanosleep.S
+++ b/libc/arch-x86/syscalls/nanosleep.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_nanosleep, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/personality.S b/libc/arch-x86/syscalls/personality.S
index d60ced1..3e003c4 100644
--- a/libc/arch-x86/syscalls/personality.S
+++ b/libc/arch-x86/syscalls/personality.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_personality, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/pipe2.S b/libc/arch-x86/syscalls/pipe2.S
index ee49ff8..8a93281 100644
--- a/libc/arch-x86/syscalls/pipe2.S
+++ b/libc/arch-x86/syscalls/pipe2.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_pipe2, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/prctl.S b/libc/arch-x86/syscalls/prctl.S
index 496591e..22b4a83 100644
--- a/libc/arch-x86/syscalls/prctl.S
+++ b/libc/arch-x86/syscalls/prctl.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_prctl, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/pread64.S b/libc/arch-x86/syscalls/pread64.S
index 42e54ec..9002f17 100644
--- a/libc/arch-x86/syscalls/pread64.S
+++ b/libc/arch-x86/syscalls/pread64.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_pread64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/prlimit64.S b/libc/arch-x86/syscalls/prlimit64.S
index 07b5585..13f6682 100644
--- a/libc/arch-x86/syscalls/prlimit64.S
+++ b/libc/arch-x86/syscalls/prlimit64.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_prlimit64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/process_vm_readv.S b/libc/arch-x86/syscalls/process_vm_readv.S
index 64965f6..e2cd044 100644
--- a/libc/arch-x86/syscalls/process_vm_readv.S
+++ b/libc/arch-x86/syscalls/process_vm_readv.S
@@ -21,14 +21,22 @@
     pushl   %ebp
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
-    mov     28(%esp), %ebx
-    mov     32(%esp), %ecx
-    mov     36(%esp), %edx
-    mov     40(%esp), %esi
-    mov     44(%esp), %edi
-    mov     48(%esp), %ebp
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     32(%esp), %ebx
+    mov     36(%esp), %ecx
+    mov     40(%esp), %edx
+    mov     44(%esp), %esi
+    mov     48(%esp), %edi
+    mov     52(%esp), %ebp
     movl    $__NR_process_vm_readv, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/process_vm_writev.S b/libc/arch-x86/syscalls/process_vm_writev.S
index 555c822..de0d218 100644
--- a/libc/arch-x86/syscalls/process_vm_writev.S
+++ b/libc/arch-x86/syscalls/process_vm_writev.S
@@ -21,14 +21,22 @@
     pushl   %ebp
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
-    mov     28(%esp), %ebx
-    mov     32(%esp), %ecx
-    mov     36(%esp), %edx
-    mov     40(%esp), %esi
-    mov     44(%esp), %edi
-    mov     48(%esp), %ebp
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     32(%esp), %ebx
+    mov     36(%esp), %ecx
+    mov     40(%esp), %edx
+    mov     44(%esp), %esi
+    mov     48(%esp), %edi
+    mov     52(%esp), %ebp
     movl    $__NR_process_vm_writev, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/pwrite64.S b/libc/arch-x86/syscalls/pwrite64.S
index d5c9b31..7532729 100644
--- a/libc/arch-x86/syscalls/pwrite64.S
+++ b/libc/arch-x86/syscalls/pwrite64.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_pwrite64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/read.S b/libc/arch-x86/syscalls/read.S
index c10a83b..d4b69b5 100644
--- a/libc/arch-x86/syscalls/read.S
+++ b/libc/arch-x86/syscalls/read.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_read, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/readahead.S b/libc/arch-x86/syscalls/readahead.S
index 1c0ccfc..8ce22bb 100644
--- a/libc/arch-x86/syscalls/readahead.S
+++ b/libc/arch-x86/syscalls/readahead.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_readahead, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/readlinkat.S b/libc/arch-x86/syscalls/readlinkat.S
index 4a24c2c..8b74a4e 100644
--- a/libc/arch-x86/syscalls/readlinkat.S
+++ b/libc/arch-x86/syscalls/readlinkat.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_readlinkat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/readv.S b/libc/arch-x86/syscalls/readv.S
index c18c1b1..a1cb08f 100644
--- a/libc/arch-x86/syscalls/readv.S
+++ b/libc/arch-x86/syscalls/readv.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_readv, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/recvfrom.S b/libc/arch-x86/syscalls/recvfrom.S
index 88c9d0a..cedd703 100644
--- a/libc/arch-x86/syscalls/recvfrom.S
+++ b/libc/arch-x86/syscalls/recvfrom.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $12, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/recvmmsg.S b/libc/arch-x86/syscalls/recvmmsg.S
index 09404d4..130332a 100644
--- a/libc/arch-x86/syscalls/recvmmsg.S
+++ b/libc/arch-x86/syscalls/recvmmsg.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $19, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/recvmsg.S b/libc/arch-x86/syscalls/recvmsg.S
index 6cfcd63..c8d2a08 100644
--- a/libc/arch-x86/syscalls/recvmsg.S
+++ b/libc/arch-x86/syscalls/recvmsg.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $17, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/removexattr.S b/libc/arch-x86/syscalls/removexattr.S
index b067a9f..ab7891e 100644
--- a/libc/arch-x86/syscalls/removexattr.S
+++ b/libc/arch-x86/syscalls/removexattr.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_removexattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/renameat.S b/libc/arch-x86/syscalls/renameat.S
index bb2181e..40caaaf 100644
--- a/libc/arch-x86/syscalls/renameat.S
+++ b/libc/arch-x86/syscalls/renameat.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_renameat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_get_priority_max.S b/libc/arch-x86/syscalls/sched_get_priority_max.S
index be66cfb..637c9dd 100644
--- a/libc/arch-x86/syscalls/sched_get_priority_max.S
+++ b/libc/arch-x86/syscalls/sched_get_priority_max.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_sched_get_priority_max, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_get_priority_min.S b/libc/arch-x86/syscalls/sched_get_priority_min.S
index 8dde67b..c38a3aa 100644
--- a/libc/arch-x86/syscalls/sched_get_priority_min.S
+++ b/libc/arch-x86/syscalls/sched_get_priority_min.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_sched_get_priority_min, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_getparam.S b/libc/arch-x86/syscalls/sched_getparam.S
index d0551ef..09901bd 100644
--- a/libc/arch-x86/syscalls/sched_getparam.S
+++ b/libc/arch-x86/syscalls/sched_getparam.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_sched_getparam, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_getscheduler.S b/libc/arch-x86/syscalls/sched_getscheduler.S
index 5b7c817..adc4023 100644
--- a/libc/arch-x86/syscalls/sched_getscheduler.S
+++ b/libc/arch-x86/syscalls/sched_getscheduler.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_sched_getscheduler, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_rr_get_interval.S b/libc/arch-x86/syscalls/sched_rr_get_interval.S
index 073f3c7..818f62e 100644
--- a/libc/arch-x86/syscalls/sched_rr_get_interval.S
+++ b/libc/arch-x86/syscalls/sched_rr_get_interval.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_sched_rr_get_interval, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_setaffinity.S b/libc/arch-x86/syscalls/sched_setaffinity.S
index 79ec113..b06d778 100644
--- a/libc/arch-x86/syscalls/sched_setaffinity.S
+++ b/libc/arch-x86/syscalls/sched_setaffinity.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_sched_setaffinity, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_setparam.S b/libc/arch-x86/syscalls/sched_setparam.S
index 970747d..dba5bc2 100644
--- a/libc/arch-x86/syscalls/sched_setparam.S
+++ b/libc/arch-x86/syscalls/sched_setparam.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_sched_setparam, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_setscheduler.S b/libc/arch-x86/syscalls/sched_setscheduler.S
index da50aaf..466a425 100644
--- a/libc/arch-x86/syscalls/sched_setscheduler.S
+++ b/libc/arch-x86/syscalls/sched_setscheduler.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_sched_setscheduler, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sched_yield.S b/libc/arch-x86/syscalls/sched_yield.S
index e3878e3..b17b14e 100644
--- a/libc/arch-x86/syscalls/sched_yield.S
+++ b/libc/arch-x86/syscalls/sched_yield.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_sched_yield, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sendfile.S b/libc/arch-x86/syscalls/sendfile.S
index c5f9a2d..e091706 100644
--- a/libc/arch-x86/syscalls/sendfile.S
+++ b/libc/arch-x86/syscalls/sendfile.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_sendfile, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sendfile64.S b/libc/arch-x86/syscalls/sendfile64.S
index bc5d0dd..317c4f4 100644
--- a/libc/arch-x86/syscalls/sendfile64.S
+++ b/libc/arch-x86/syscalls/sendfile64.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_sendfile64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sendmmsg.S b/libc/arch-x86/syscalls/sendmmsg.S
index 784c6b6..c0097f8 100644
--- a/libc/arch-x86/syscalls/sendmmsg.S
+++ b/libc/arch-x86/syscalls/sendmmsg.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $20, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sendmsg.S b/libc/arch-x86/syscalls/sendmsg.S
index bf0d1fb..775ebee 100644
--- a/libc/arch-x86/syscalls/sendmsg.S
+++ b/libc/arch-x86/syscalls/sendmsg.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $16, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sendto.S b/libc/arch-x86/syscalls/sendto.S
index b39eaf0..2df5e4f 100644
--- a/libc/arch-x86/syscalls/sendto.S
+++ b/libc/arch-x86/syscalls/sendto.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $11, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setfsgid.S b/libc/arch-x86/syscalls/setfsgid.S
index dc81f72..af4ef89 100644
--- a/libc/arch-x86/syscalls/setfsgid.S
+++ b/libc/arch-x86/syscalls/setfsgid.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_setfsgid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setfsuid.S b/libc/arch-x86/syscalls/setfsuid.S
index fdf7850..8001e42 100644
--- a/libc/arch-x86/syscalls/setfsuid.S
+++ b/libc/arch-x86/syscalls/setfsuid.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_setfsuid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setgid.S b/libc/arch-x86/syscalls/setgid.S
index ce6ee26..c0ddec4 100644
--- a/libc/arch-x86/syscalls/setgid.S
+++ b/libc/arch-x86/syscalls/setgid.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_setgid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setgroups.S b/libc/arch-x86/syscalls/setgroups.S
index 7e46ad0..7bd3bfc 100644
--- a/libc/arch-x86/syscalls/setgroups.S
+++ b/libc/arch-x86/syscalls/setgroups.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_setgroups32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sethostname.S b/libc/arch-x86/syscalls/sethostname.S
index bfcfd73..26ff1e7 100644
--- a/libc/arch-x86/syscalls/sethostname.S
+++ b/libc/arch-x86/syscalls/sethostname.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_sethostname, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setitimer.S b/libc/arch-x86/syscalls/setitimer.S
index 370ab5e..063847b 100644
--- a/libc/arch-x86/syscalls/setitimer.S
+++ b/libc/arch-x86/syscalls/setitimer.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_setitimer, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setns.S b/libc/arch-x86/syscalls/setns.S
index 736df59..28d838e 100644
--- a/libc/arch-x86/syscalls/setns.S
+++ b/libc/arch-x86/syscalls/setns.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_setns, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setpgid.S b/libc/arch-x86/syscalls/setpgid.S
index 0bff10a..c5d0d27 100644
--- a/libc/arch-x86/syscalls/setpgid.S
+++ b/libc/arch-x86/syscalls/setpgid.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_setpgid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setpriority.S b/libc/arch-x86/syscalls/setpriority.S
index 4233871..17c81c6 100644
--- a/libc/arch-x86/syscalls/setpriority.S
+++ b/libc/arch-x86/syscalls/setpriority.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_setpriority, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setregid.S b/libc/arch-x86/syscalls/setregid.S
index a56ccfd..dd8101a 100644
--- a/libc/arch-x86/syscalls/setregid.S
+++ b/libc/arch-x86/syscalls/setregid.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_setregid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setresgid.S b/libc/arch-x86/syscalls/setresgid.S
index 2299831..6f6de5a 100644
--- a/libc/arch-x86/syscalls/setresgid.S
+++ b/libc/arch-x86/syscalls/setresgid.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_setresgid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setresuid.S b/libc/arch-x86/syscalls/setresuid.S
index 8624e15..ab0059c 100644
--- a/libc/arch-x86/syscalls/setresuid.S
+++ b/libc/arch-x86/syscalls/setresuid.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_setresuid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setreuid.S b/libc/arch-x86/syscalls/setreuid.S
index 9f6e117..7fda62e 100644
--- a/libc/arch-x86/syscalls/setreuid.S
+++ b/libc/arch-x86/syscalls/setreuid.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_setreuid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setrlimit.S b/libc/arch-x86/syscalls/setrlimit.S
index 2024688..595633e 100644
--- a/libc/arch-x86/syscalls/setrlimit.S
+++ b/libc/arch-x86/syscalls/setrlimit.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_setrlimit, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setsid.S b/libc/arch-x86/syscalls/setsid.S
index dda6ad8..80ad8a9 100644
--- a/libc/arch-x86/syscalls/setsid.S
+++ b/libc/arch-x86/syscalls/setsid.S
@@ -3,8 +3,16 @@
 #include <private/bionic_asm.h>
 
 ENTRY(setsid)
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     movl    $__NR_setsid, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setsockopt.S b/libc/arch-x86/syscalls/setsockopt.S
index 29e73bb..bca34e1 100644
--- a/libc/arch-x86/syscalls/setsockopt.S
+++ b/libc/arch-x86/syscalls/setsockopt.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $14, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/settimeofday.S b/libc/arch-x86/syscalls/settimeofday.S
index 4a861ab..31437d0 100644
--- a/libc/arch-x86/syscalls/settimeofday.S
+++ b/libc/arch-x86/syscalls/settimeofday.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_settimeofday, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setuid.S b/libc/arch-x86/syscalls/setuid.S
index 048e0c1..2461182 100644
--- a/libc/arch-x86/syscalls/setuid.S
+++ b/libc/arch-x86/syscalls/setuid.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_setuid32, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/setxattr.S b/libc/arch-x86/syscalls/setxattr.S
index 1e87bf0..787891e 100644
--- a/libc/arch-x86/syscalls/setxattr.S
+++ b/libc/arch-x86/syscalls/setxattr.S
@@ -18,13 +18,21 @@
     pushl   %edi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edi, 0
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     28(%esp), %ebx
+    mov     32(%esp), %ecx
+    mov     36(%esp), %edx
+    mov     40(%esp), %esi
+    mov     44(%esp), %edi
     movl    $__NR_setxattr, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/shutdown.S b/libc/arch-x86/syscalls/shutdown.S
index f224fc6..46e5c18 100644
--- a/libc/arch-x86/syscalls/shutdown.S
+++ b/libc/arch-x86/syscalls/shutdown.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $13, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sigaltstack.S b/libc/arch-x86/syscalls/sigaltstack.S
index 875ef8c..90eae16 100644
--- a/libc/arch-x86/syscalls/sigaltstack.S
+++ b/libc/arch-x86/syscalls/sigaltstack.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_sigaltstack, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/socketpair.S b/libc/arch-x86/syscalls/socketpair.S
index 4c5154e..c9c7595 100644
--- a/libc/arch-x86/syscalls/socketpair.S
+++ b/libc/arch-x86/syscalls/socketpair.S
@@ -9,11 +9,19 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
     mov     $8, %ebx
     mov     %esp, %ecx
-    addl    $12, %ecx
+    addl    $16, %ecx
     movl    $__NR_socketcall, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/splice.S b/libc/arch-x86/syscalls/splice.S
index 1dc9037..2d82a3d 100644
--- a/libc/arch-x86/syscalls/splice.S
+++ b/libc/arch-x86/syscalls/splice.S
@@ -21,14 +21,22 @@
     pushl   %ebp
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ebp, 0
-    mov     28(%esp), %ebx
-    mov     32(%esp), %ecx
-    mov     36(%esp), %edx
-    mov     40(%esp), %esi
-    mov     44(%esp), %edi
-    mov     48(%esp), %ebp
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     32(%esp), %ebx
+    mov     36(%esp), %ecx
+    mov     40(%esp), %edx
+    mov     44(%esp), %esi
+    mov     48(%esp), %edi
+    mov     52(%esp), %ebp
     movl    $__NR_splice, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/swapoff.S b/libc/arch-x86/syscalls/swapoff.S
index 0788529..d10a748 100644
--- a/libc/arch-x86/syscalls/swapoff.S
+++ b/libc/arch-x86/syscalls/swapoff.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_swapoff, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/swapon.S b/libc/arch-x86/syscalls/swapon.S
index 1070d8e..dc7db64 100644
--- a/libc/arch-x86/syscalls/swapon.S
+++ b/libc/arch-x86/syscalls/swapon.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_swapon, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/symlinkat.S b/libc/arch-x86/syscalls/symlinkat.S
index e7fe69e..51b1330 100644
--- a/libc/arch-x86/syscalls/symlinkat.S
+++ b/libc/arch-x86/syscalls/symlinkat.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_symlinkat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sync.S b/libc/arch-x86/syscalls/sync.S
index 252c666..c75e9f9 100644
--- a/libc/arch-x86/syscalls/sync.S
+++ b/libc/arch-x86/syscalls/sync.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_sync, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/sysinfo.S b/libc/arch-x86/syscalls/sysinfo.S
index f59a0c3..a40d664 100644
--- a/libc/arch-x86/syscalls/sysinfo.S
+++ b/libc/arch-x86/syscalls/sysinfo.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_sysinfo, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/tee.S b/libc/arch-x86/syscalls/tee.S
index b47c460..693ad1e 100644
--- a/libc/arch-x86/syscalls/tee.S
+++ b/libc/arch-x86/syscalls/tee.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_tee, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/tgkill.S b/libc/arch-x86/syscalls/tgkill.S
index 7a43a01..5cce4d8 100644
--- a/libc/arch-x86/syscalls/tgkill.S
+++ b/libc/arch-x86/syscalls/tgkill.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_tgkill, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/timerfd_create.S b/libc/arch-x86/syscalls/timerfd_create.S
index ad099a5..335b7a6 100644
--- a/libc/arch-x86/syscalls/timerfd_create.S
+++ b/libc/arch-x86/syscalls/timerfd_create.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_timerfd_create, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/timerfd_gettime.S b/libc/arch-x86/syscalls/timerfd_gettime.S
index c679b7c..9dc1a2f 100644
--- a/libc/arch-x86/syscalls/timerfd_gettime.S
+++ b/libc/arch-x86/syscalls/timerfd_gettime.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_timerfd_gettime, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/timerfd_settime.S b/libc/arch-x86/syscalls/timerfd_settime.S
index 4e889ea..477b5bb 100644
--- a/libc/arch-x86/syscalls/timerfd_settime.S
+++ b/libc/arch-x86/syscalls/timerfd_settime.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_timerfd_settime, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/times.S b/libc/arch-x86/syscalls/times.S
index 0ba0b6f..14fe221 100644
--- a/libc/arch-x86/syscalls/times.S
+++ b/libc/arch-x86/syscalls/times.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_times, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/truncate.S b/libc/arch-x86/syscalls/truncate.S
index 31fec17..dd99942 100644
--- a/libc/arch-x86/syscalls/truncate.S
+++ b/libc/arch-x86/syscalls/truncate.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_truncate, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/truncate64.S b/libc/arch-x86/syscalls/truncate64.S
index 45e24d0..35e4037 100644
--- a/libc/arch-x86/syscalls/truncate64.S
+++ b/libc/arch-x86/syscalls/truncate64.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_truncate64, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/umask.S b/libc/arch-x86/syscalls/umask.S
index 9b4d3c7..3333fac 100644
--- a/libc/arch-x86/syscalls/umask.S
+++ b/libc/arch-x86/syscalls/umask.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_umask, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/umount2.S b/libc/arch-x86/syscalls/umount2.S
index 13757ab..48e1eb5 100644
--- a/libc/arch-x86/syscalls/umount2.S
+++ b/libc/arch-x86/syscalls/umount2.S
@@ -9,10 +9,18 @@
     pushl   %ecx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset ecx, 0
-    mov     12(%esp), %ebx
-    mov     16(%esp), %ecx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
     movl    $__NR_umount2, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/uname.S b/libc/arch-x86/syscalls/uname.S
index dab7e0d..9eea2c1 100644
--- a/libc/arch-x86/syscalls/uname.S
+++ b/libc/arch-x86/syscalls/uname.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_uname, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/unlinkat.S b/libc/arch-x86/syscalls/unlinkat.S
index 6faf71e..e039a34 100644
--- a/libc/arch-x86/syscalls/unlinkat.S
+++ b/libc/arch-x86/syscalls/unlinkat.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_unlinkat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/unshare.S b/libc/arch-x86/syscalls/unshare.S
index b724798..ae68d7e 100644
--- a/libc/arch-x86/syscalls/unshare.S
+++ b/libc/arch-x86/syscalls/unshare.S
@@ -6,9 +6,17 @@
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
-    mov     8(%esp), %ebx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     12(%esp), %ebx
     movl    $__NR_unshare, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/utimensat.S b/libc/arch-x86/syscalls/utimensat.S
index 07eca45..43eebc7 100644
--- a/libc/arch-x86/syscalls/utimensat.S
+++ b/libc/arch-x86/syscalls/utimensat.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_utimensat, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/vmsplice.S b/libc/arch-x86/syscalls/vmsplice.S
index f12cc65..195b0bf 100644
--- a/libc/arch-x86/syscalls/vmsplice.S
+++ b/libc/arch-x86/syscalls/vmsplice.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_vmsplice, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/wait4.S b/libc/arch-x86/syscalls/wait4.S
index bed7c40..281d5f2 100644
--- a/libc/arch-x86/syscalls/wait4.S
+++ b/libc/arch-x86/syscalls/wait4.S
@@ -15,12 +15,20 @@
     pushl   %esi
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset esi, 0
-    mov     20(%esp), %ebx
-    mov     24(%esp), %ecx
-    mov     28(%esp), %edx
-    mov     32(%esp), %esi
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     24(%esp), %ebx
+    mov     28(%esp), %ecx
+    mov     32(%esp), %edx
+    mov     36(%esp), %esi
     movl    $__NR_wait4, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/write.S b/libc/arch-x86/syscalls/write.S
index e147208..e9e5f4e 100644
--- a/libc/arch-x86/syscalls/write.S
+++ b/libc/arch-x86/syscalls/write.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_write, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86/syscalls/writev.S b/libc/arch-x86/syscalls/writev.S
index 07ba7b5..6649905 100644
--- a/libc/arch-x86/syscalls/writev.S
+++ b/libc/arch-x86/syscalls/writev.S
@@ -12,11 +12,19 @@
     pushl   %edx
     .cfi_adjust_cfa_offset 4
     .cfi_rel_offset edx, 0
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
     movl    $__NR_writev, %eax
-    int     $0x80
+    call    *(%esp)
+    addl    $4, %esp
+
     cmpl    $-MAX_ERRNO, %eax
     jb      1f
     negl    %eax
diff --git a/libc/arch-x86_64/bionic/setjmp.S b/libc/arch-x86_64/bionic/setjmp.S
index 56ebb07..34b4365 100644
--- a/libc/arch-x86_64/bionic/setjmp.S
+++ b/libc/arch-x86_64/bionic/setjmp.S
@@ -35,8 +35,22 @@
 
 #include <private/bionic_asm.h>
 
-// These are only the callee-saved registers. Code calling setjmp
-// will expect the rest to be clobbered anyway.
+
+// The internal structure of a jmp_buf is totally private.
+// Current layout (changes from release to release):
+//
+// word   name            description
+// 0      rbx             registers
+// 1      rbp
+// 2      r12
+// 3      r13
+// 4      r14
+// 5      r15
+// 6      rsp
+// 7      pc
+// 8      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
+// 9      sigmask         signal mask (includes rt signals as well)
+// 10     checksum        checksum of the core registers, to give better error messages.
 
 #define _JB_RBX 0
 #define _JB_RBP 1
@@ -48,9 +62,10 @@
 #define _JB_PC 7
 #define _JB_SIGFLAG 8
 #define _JB_SIGMASK 9
-#define _JB_SIGMASK_RT 10 // sigprocmask will write here too.
+#define _JB_CHECKSUM 10
 
 #define MANGLE_REGISTERS 1
+
 .macro m_mangle_registers reg
 #if MANGLE_REGISTERS
   xorq \reg,%rbx
@@ -68,6 +83,12 @@
   m_mangle_registers \reg
 .endm
 
+.macro m_calculate_checksum dst, src
+  movq $0, \dst
+  .irp i,0,1,2,3,4,5,6,7
+    xorq (\i*8)(\src), \dst
+  .endr
+.endm
 
 ENTRY(setjmp)
   movl $1,%esi
@@ -118,6 +139,9 @@
   movq %r11,(_JB_PC  * 8)(%rdi)
   m_unmangle_registers %rax
 
+  m_calculate_checksum %rax, %rdi
+  movq %rax, (_JB_CHECKSUM * 8)(%rdi)
+
   xorl %eax,%eax
   ret
 END(sigsetjmp)
@@ -127,6 +151,10 @@
   movq %rdi,%r12
   pushq %rsi // Push 'value'.
 
+  m_calculate_checksum %rax, %rdi
+  xorq (_JB_CHECKSUM * 8)(%rdi), %rax
+  jnz 3f
+
   // Do we need to restore the signal mask?
   movq (_JB_SIGFLAG * 8)(%rdi), %rdi
   pushq %rdi // Push cookie
@@ -172,6 +200,9 @@
 1:
   movq %r11,0(%rsp)
   ret
+
+3:
+  call PIC_PLT(__bionic_setjmp_checksum_mismatch)
 END(siglongjmp)
 
 ALIAS_SYMBOL(longjmp, siglongjmp)
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index a29d8a7..01bb9bb 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -51,6 +51,9 @@
 
 void __libc_init_main_thread(KernelArgumentBlock& args) {
   __libc_auxv = args.auxv;
+#if defined(__i386__)
+  __libc_init_sysinfo(args);
+#endif
 
   static pthread_internal_t main_thread;
 
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index c2a5fed..4f1226d 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -70,7 +70,23 @@
   __stack_chk_guard = *reinterpret_cast<uintptr_t*>(args.getauxval(AT_RANDOM));
 }
 
+#if defined(__i386__)
+__LIBC_HIDDEN__ void* __libc_sysinfo = nullptr;
+
+__LIBC_HIDDEN__ void __libc_init_sysinfo(KernelArgumentBlock& args) {
+  __libc_sysinfo = reinterpret_cast<void*>(args.getauxval(AT_SYSINFO));
+}
+
+// TODO: lose this function and just access __libc_sysinfo directly.
+extern "C" void* __kernel_syscall() {
+  return __libc_sysinfo;
+}
+#endif
+
 void __libc_init_globals(KernelArgumentBlock& args) {
+#if defined(__i386__)
+  __libc_init_sysinfo(args);
+#endif
   // Initialize libc globals that are needed in both the linker and in libc.
   // In dynamic binaries, this is run at least twice for different copies of the
   // globals, once for the linker's copy and once for the one in libc.so.
diff --git a/libc/dns/include/resolv_netid.h b/libc/dns/include/resolv_netid.h
index d364645..09c5498 100644
--- a/libc/dns/include/resolv_netid.h
+++ b/libc/dns/include/resolv_netid.h
@@ -49,6 +49,7 @@
 
 __BEGIN_DECLS
 
+struct __res_params;
 struct addrinfo;
 
 #define __used_in_netd __attribute__((visibility ("default")))
@@ -86,8 +87,8 @@
     const struct android_net_context *, struct addrinfo **) __used_in_netd;
 
 /* set name servers for a network */
-extern void _resolv_set_nameservers_for_net(unsigned netid,
-    const char** servers, int numservers, const char *domains) __used_in_netd;
+extern void _resolv_set_nameservers_for_net(unsigned netid, const char** servers, int numservers,
+	const char *domains, const struct __res_params* params) __used_in_netd;
 
 /* flush the cache associated with a certain network */
 extern void _resolv_flush_cache_for_net(unsigned netid) __used_in_netd;
diff --git a/libc/dns/include/resolv_params.h b/libc/dns/include/resolv_params.h
new file mode 100644
index 0000000..353ae4d
--- /dev/null
+++ b/libc/dns/include/resolv_params.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _RESOLV_PARAMS_H
+#define _RESOLV_PARAMS_H
+
+#include <stdint.h>
+
+/* Hard-coded defines */
+#define	MAXNS			3	/* max # name servers we'll track */
+#define	MAXNSSAMPLES		64	/* max # samples to store per server */
+
+/* Defaults used for initializing __res_params */
+#define SUCCESS_THRESHOLD       75      /* if successes * 100 / total_samples is less than
+					 * this value, the server is considered failing
+					 */
+#define NSSAMPLE_VALIDITY	1800	/* Sample validity in seconds.
+					 * Set to -1 to disable skipping failing
+					 * servers.
+					 */
+
+/* per-netid configuration parameters passed from netd to the resolver */
+struct __res_params {
+    uint16_t sample_validity; // sample lifetime in s
+    // threshold of success / total samples below which a server is considered broken
+    uint8_t success_threshold; // 0: disable, value / 100 otherwise
+    uint8_t min_samples; // min # samples needed for statistics to be considered meaningful
+    uint8_t max_samples; // max # samples taken into account for statistics
+} __attribute__((__packed__));
+
+#endif // _RESOLV_PARAMS_H
diff --git a/libc/dns/include/resolv_private.h b/libc/dns/include/resolv_private.h
index 9484d0e..8cdcc2e 100644
--- a/libc/dns/include/resolv_private.h
+++ b/libc/dns/include/resolv_private.h
@@ -58,7 +58,10 @@
 
 #include <resolv.h>
 #include "resolv_static.h"
+#include "resolv_params.h"
+#include "resolv_stats.h"
 #include <net/if.h>
+#include <time.h>
 
 /* Despite this file's name, it's part of libresolv. On Android, that means it's part of libc :-( */
 #pragma GCC visibility push(default)
@@ -136,7 +139,6 @@
 /*
  * Global defines and variables for resolver stub.
  */
-#define	MAXNS			3	/* max # name servers we'll track */
 #define	MAXDFLSRCH		3	/* # default domain levels to try */
 #define	MAXDNSRCH		6	/* max # domains in search path */
 #define	LOCALDOMAINPARTS	2	/* min levels in name that is "local" */
@@ -205,6 +207,24 @@
 
 typedef struct __res_state *res_state;
 
+/* Retrieve a local copy of the stats for the given netid. The buffer must have space for
+ * MAXNS __resolver_stats. Returns the revision id of the resolvers used.
+ */
+__LIBC_HIDDEN__
+extern int
+_resolv_cache_get_resolver_stats( unsigned netid, struct __res_params* params,
+        struct __res_stats stats[MAXNS]);
+
+/* Add a sample to the shared struct for the given netid and server, provided that the
+ * revision_id of the stored servers has not changed.
+ */
+__LIBC_HIDDEN__
+extern void
+_resolv_cache_add_resolver_stats_sample( unsigned netid, int revision_id, int ns,
+        const struct __res_sample* sample, int max_samples);
+
+/* End of stats related definitions */
+
 union res_sockaddr_union {
 	struct sockaddr_in	sin;
 #ifdef IN6ADDR_ANY_INIT
diff --git a/libc/dns/include/resolv_stats.h b/libc/dns/include/resolv_stats.h
new file mode 100644
index 0000000..aaf6bd8
--- /dev/null
+++ b/libc/dns/include/resolv_stats.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _RES_STATS_H
+#define _RES_STATS_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <time.h>
+
+#include "resolv_params.h"
+
+#define RCODE_INTERNAL_ERROR    254
+#define RCODE_TIMEOUT           255
+
+/*
+ * Resolver reachability statistics and run-time parameters.
+ */
+
+struct __res_sample {
+    time_t			at;    // time in s at which the sample was recorded
+    uint16_t			rtt;   // round-trip time in ms
+    uint8_t			rcode; // the DNS rcode or RCODE_XXX defined above
+};
+
+struct __res_stats {
+    // Stats of the last <sample_count> queries.
+    struct __res_sample		samples[MAXNSSAMPLES];
+    // The number of samples stored.
+    uint8_t			sample_count;
+    // The next sample to modify.
+    uint8_t			sample_next;
+};
+
+/* Calculate the round-trip-time from start time t0 and end time t1. */
+int
+_res_stats_calculate_rtt(const struct timespec* t1, const struct timespec* t0);
+
+/* Initialize a sample for calculating server reachability statistics. */
+extern void
+_res_stats_set_sample(struct __res_sample* sample, time_t now, int rcode, int rtt);
+
+/* Aggregates the reachability statistics for the given server based on on the stored samples. */
+extern void
+_res_stats_aggregate(struct __res_stats* stats, int* successes, int* errors, int* timeouts,
+             int* internal_errors, int* rtt_avg, time_t* last_sample_time);
+
+/* Returns true if the server is considered unusable, i.e. if the success rate is not lower than the
+ * threshold for the stored stored samples. If not enough samples are stored, the server is
+ * considered usable.
+ */
+extern bool
+_res_stats_usable_server(const struct __res_params* params, struct __res_stats* stats);
+
+/* Returns an array of bools indicating which servers are considered good */
+extern void
+_res_stats_get_usable_servers(const struct __res_params* params, struct __res_stats stats[],
+        int nscount, bool valid_servers[]);
+
+#endif  // _RES_STATS_H
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index 5a78450..15f9aa4 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -1228,12 +1228,18 @@
     PendingReqInfo   pending_requests;
 } Cache;
 
+// The nameservers[], nsaddrinfo[] and nsstats[] are containing MAXNS + 1 elements, because the
+// number of nameservers is not known and the code relies on the n+1-st entry to be null to
+// recognize the end.
 struct resolv_cache_info {
     unsigned                    netid;
     Cache*                      cache;
     struct resolv_cache_info*   next;
-    char*                       nameservers[MAXNS +1];
+    char*                       nameservers[MAXNS + 1];
     struct addrinfo*            nsaddrinfo[MAXNS + 1];
+    int                         revision_id; // # times the nameservers have been replaced
+    struct __res_params         params;
+    struct __res_stats          nsstats[MAXNS + 1];
     char                        defdname[256];
     int                         dnsrch_offset[MAXDNSRCH+1];  // offsets into defdname
 };
@@ -1361,6 +1367,8 @@
     pthread_mutex_unlock(&_res_cache_list_lock);
 }
 
+static struct resolv_cache_info* _find_cache_info_locked(unsigned netid);
+
 static void
 _cache_flush_locked( Cache*  cache )
 {
@@ -1801,6 +1809,8 @@
  * currently attached to the provided cache_info */
 static int _resolv_is_nameservers_equal_locked(struct resolv_cache_info* cache_info,
         const char** servers, int numservers);
+/* clears the stats samples contained withing the given cache_info */
+static void _res_cache_clear_stats_locked(struct resolv_cache_info* cache_info);
 
 static void
 _res_cache_init(void)
@@ -1854,6 +1864,10 @@
     if (cache) {
         _cache_flush_locked(cache);
     }
+
+    // Also clear the NS statistics.
+    struct resolv_cache_info* cache_info = _find_cache_info_locked(netid);
+    _res_cache_clear_stats_locked(cache_info);
 }
 
 void _resolv_delete_cache_for_net(unsigned netid)
@@ -1928,8 +1942,16 @@
 }
 
 void
+_resolv_set_default_params(struct __res_params* params) {
+    params->sample_validity = NSSAMPLE_VALIDITY;
+    params->success_threshold = SUCCESS_THRESHOLD;
+    params->min_samples = 0;
+    params->max_samples = 0;
+}
+
+void
 _resolv_set_nameservers_for_net(unsigned netid, const char** servers, int numservers,
-        const char *domains)
+        const char *domains, const struct __res_params* params)
 {
     int i, rt, index;
     struct addrinfo hints;
@@ -1945,54 +1967,76 @@
 
     struct resolv_cache_info* cache_info = _find_cache_info_locked(netid);
 
-    if (cache_info != NULL &&
-            !_resolv_is_nameservers_equal_locked(cache_info, servers, numservers)) {
-        // free current before adding new
-        _free_nameservers_locked(cache_info);
-
-        memset(&hints, 0, sizeof(hints));
-        hints.ai_family = PF_UNSPEC;
-        hints.ai_socktype = SOCK_DGRAM; /*dummy*/
-        hints.ai_flags = AI_NUMERICHOST;
-        snprintf(sbuf, sizeof(sbuf), "%u", NAMESERVER_PORT);
-
-        index = 0;
-        for (i = 0; i < numservers && i < MAXNS; i++) {
-            rt = getaddrinfo(servers[i], sbuf, &hints, &cache_info->nsaddrinfo[index]);
-            if (rt == 0) {
-                cache_info->nameservers[index] = strdup(servers[i]);
-                index++;
-                XLOG("%s: netid = %u, addr = %s\n", __FUNCTION__, netid, servers[i]);
-            } else {
-                cache_info->nsaddrinfo[index] = NULL;
-            }
+    if (cache_info != NULL) {
+        uint8_t old_max_samples = cache_info->params.max_samples;
+        if (params != NULL) {
+            cache_info->params = *params;
+        } else {
+            _resolv_set_default_params(&cache_info->params);
         }
 
-        // code moved from res_init.c, load_domain_search_list
-        strlcpy(cache_info->defdname, domains, sizeof(cache_info->defdname));
-        if ((cp = strchr(cache_info->defdname, '\n')) != NULL)
-            *cp = '\0';
-        cp = cache_info->defdname;
-        offset = cache_info->dnsrch_offset;
-        while (offset < cache_info->dnsrch_offset + MAXDNSRCH) {
-            while (*cp == ' ' || *cp == '\t') /* skip leading white space */
-                cp++;
-            if (*cp == '\0') /* stop if nothing more to do */
-                break;
-            *offset++ = cp - cache_info->defdname; /* record this search domain */
-            while (*cp) { /* zero-terminate it */
-                if (*cp == ' '|| *cp == '\t') {
-                    *cp++ = '\0';
-                    break;
+        if (!_resolv_is_nameservers_equal_locked(cache_info, servers, numservers)) {
+            // free current before adding new
+            _free_nameservers_locked(cache_info);
+
+            memset(&hints, 0, sizeof(hints));
+            hints.ai_family = PF_UNSPEC;
+            hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+            hints.ai_flags = AI_NUMERICHOST;
+            snprintf(sbuf, sizeof(sbuf), "%u", NAMESERVER_PORT);
+
+            index = 0;
+            for (i = 0; i < numservers && i < MAXNS; i++) {
+                rt = getaddrinfo(servers[i], sbuf, &hints, &cache_info->nsaddrinfo[index]);
+                if (rt == 0) {
+                    cache_info->nameservers[index] = strdup(servers[i]);
+                    index++;
+                    XLOG("%s: netid = %u, addr = %s\n", __FUNCTION__, netid, servers[i]);
+                } else {
+                    cache_info->nsaddrinfo[index] = NULL;
                 }
-                cp++;
             }
-        }
-        *offset = -1; /* cache_info->dnsrch_offset has MAXDNSRCH+1 items */
 
-        // flush cache since new settings
-        _flush_cache_for_net_locked(netid);
+            // code moved from res_init.c, load_domain_search_list
+            strlcpy(cache_info->defdname, domains, sizeof(cache_info->defdname));
+            if ((cp = strchr(cache_info->defdname, '\n')) != NULL)
+                *cp = '\0';
 
+            cp = cache_info->defdname;
+            offset = cache_info->dnsrch_offset;
+            while (offset < cache_info->dnsrch_offset + MAXDNSRCH) {
+                while (*cp == ' ' || *cp == '\t') /* skip leading white space */
+                    cp++;
+                if (*cp == '\0') /* stop if nothing more to do */
+                    break;
+                *offset++ = cp - cache_info->defdname; /* record this search domain */
+                while (*cp) { /* zero-terminate it */
+                    if (*cp == ' '|| *cp == '\t') {
+                        *cp++ = '\0';
+                        break;
+                    }
+                    cp++;
+                }
+            }
+            *offset = -1; /* cache_info->dnsrch_offset has MAXDNSRCH+1 items */
+
+            // Flush the cache and reset the stats.
+            _flush_cache_for_net_locked(netid);
+
+            // increment the revision id to ensure that sample state is not written back if the
+            // servers change; in theory it would suffice to do so only if the servers or
+            // max_samples actually change, in practice the overhead of checking is higher than the
+            // cost, and overflows are unlikely
+            ++cache_info->revision_id;
+       } else if (cache_info->params.max_samples != old_max_samples) {
+           // If the maximum number of samples changes, the overhead of keeping the most recent
+           // samples around is not considered worth the effort, so they are cleared instead. All
+           // other parameters do not affect shared state: Changing these parameters does not
+           // invalidate the samples, as they only affect aggregation and the conditions under which
+           // servers are considered usable.
+           _res_cache_clear_stats_locked(cache_info);
+           ++cache_info->revision_id;
+       }
     }
 
     pthread_mutex_unlock(&_res_cache_list_lock);
@@ -2049,7 +2093,11 @@
             freeaddrinfo(cache_info->nsaddrinfo[i]);
             cache_info->nsaddrinfo[i] = NULL;
         }
+        cache_info->nsstats[i].sample_count =
+            cache_info->nsstats[i].sample_next = 0;
     }
+    _res_cache_clear_stats_locked(cache_info);
+    ++cache_info->revision_id;
 }
 
 void
@@ -2093,7 +2141,8 @@
         statp->nscount = nserv;
         // now do search domains.  Note that we cache the offsets as this code runs alot
         // but the setting/offset-computer only runs when set/changed
-        strlcpy(statp->defdname, info->defdname, sizeof(statp->defdname));
+        // WARNING: Don't use str*cpy() here, this string contains zeroes.
+        memcpy(statp->defdname, info->defdname, sizeof(statp->defdname));
         register char **pp = statp->dnsrch;
         register int *p = info->dnsrch_offset;
         while (pp < statp->dnsrch + MAXDNSRCH && *p != -1) {
@@ -2102,3 +2151,65 @@
     }
     pthread_mutex_unlock(&_res_cache_list_lock);
 }
+
+/* Resolver reachability statistics. */
+
+static void
+_res_cache_add_stats_sample_locked(struct __res_stats* stats, const struct __res_sample* sample,
+        int max_samples) {
+    // Note: This function expects max_samples > 0, otherwise a (harmless) modification of the
+    // allocated but supposedly unused memory for samples[0] will happen
+    XLOG("%s: adding sample to stats, next = %d, count = %d", __FUNCTION__,
+            stats->sample_next, stats->sample_count);
+    stats->samples[stats->sample_next] = *sample;
+    if (stats->sample_count < max_samples) {
+        ++stats->sample_count;
+    }
+    if (++stats->sample_next >= max_samples) {
+        stats->sample_next = 0;
+    }
+}
+
+static void
+_res_cache_clear_stats_locked(struct resolv_cache_info* cache_info) {
+    if (cache_info) {
+        for (int i = 0 ; i < MAXNS ; ++i) {
+            cache_info->nsstats->sample_count = cache_info->nsstats->sample_next = 0;
+        }
+    }
+}
+
+int
+_resolv_cache_get_resolver_stats( unsigned netid, struct __res_params* params,
+        struct __res_stats stats[MAXNS]) {
+
+    int revision_id = -1;
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    struct resolv_cache_info* info = _find_cache_info_locked(netid);
+    if (info) {
+        memcpy(stats, info->nsstats, sizeof(info->nsstats));
+        *params = info->params;
+        revision_id = info->revision_id;
+    }
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+    return revision_id;
+}
+
+void
+_resolv_cache_add_resolver_stats_sample( unsigned netid, int revision_id, int ns,
+       const struct __res_sample* sample, int max_samples) {
+    if (max_samples <= 0) return;
+
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    struct resolv_cache_info* info = _find_cache_info_locked(netid);
+
+    if (info && info->revision_id == revision_id) {
+        _res_cache_add_stats_sample_locked(&info->nsstats[ns], sample, max_samples);
+    }
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+}
+
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index a8da3ac..df8e131 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -81,9 +81,6 @@
 #endif
 #endif /* LIBC_SCCS and not lint */
 
-/* set to 1 to use our small/simple/limited DNS cache */
-#define  USE_RESOLV_CACHE  1
-
 /*
  * Send query to name server and wait for reply.
  */
@@ -116,9 +113,7 @@
 
 #include <isc/eventlib.h>
 
-#if USE_RESOLV_CACHE
-#  include <resolv_cache.h>
-#endif
+#include <resolv_cache.h>
 
 #include "private/libc_logging.h"
 
@@ -133,6 +128,7 @@
 #endif
 #include "res_debug.h"
 #include "res_private.h"
+#include "resolv_stats.h"
 
 #define EXT(res) ((res)->_u._ext)
 #define DBG 0
@@ -144,10 +140,12 @@
 static int		get_salen __P((const struct sockaddr *));
 static struct sockaddr * get_nsaddr __P((res_state, size_t));
 static int		send_vc(res_state, const u_char *, int,
-				u_char *, int, int *, int);
+				u_char *, int, int *, int,
+				time_t *, int *, int *);
 static int		send_dg(res_state, const u_char *, int,
 				u_char *, int, int *, int,
-				int *, int *);
+				int *, int *,
+				time_t *, int *, int *);
 static void		Aerror(const res_state, FILE *, const char *, int,
 			       const struct sockaddr *, int);
 static void		Perror(const res_state, FILE *, const char *, int);
@@ -359,23 +357,13 @@
 	return (1);
 }
 
-
 int
 res_nsend(res_state statp,
 	  const u_char *buf, int buflen, u_char *ans, int anssiz)
 {
 	int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
 	char abuf[NI_MAXHOST];
-#if USE_RESOLV_CACHE
-        ResolvCacheStatus     cache_status = RESOLV_CACHE_UNSUPPORTED;
-#endif
-
-#if !USE_RESOLV_CACHE
-	if (statp->nscount == 0) {
-		errno = ESRCH;
-		return (-1);
-	}
-#endif
+	ResolvCacheStatus     cache_status = RESOLV_CACHE_UNSUPPORTED;
 
 	if (anssiz < HFIXEDSZ) {
 		errno = EINVAL;
@@ -387,7 +375,6 @@
 	gotsomewhere = 0;
 	terrno = ETIMEDOUT;
 
-#if USE_RESOLV_CACHE
 	int  anslen = 0;
 	cache_status = _resolv_cache_lookup(
 			statp->netid, buf, buflen,
@@ -400,7 +387,6 @@
 		// data so the normal resolve path can do its thing
 		_resolv_populate_res_for_net(statp);
 	}
-
 	if (statp->nscount == 0) {
 		// We have no nameservers configured, so there's no point trying.
 		// Tell the cache the query failed, or any retries and anyone else asking the same
@@ -409,7 +395,6 @@
 		errno = ESRCH;
 		return (-1);
 	}
-#endif
 
 	/*
 	 * If the ns_addr_list in the resolver context has changed, then
@@ -420,9 +405,9 @@
 		struct sockaddr_storage peer;
 		socklen_t peerlen;
 
-		if (EXT(statp).nscount != statp->nscount)
+		if (EXT(statp).nscount != statp->nscount) {
 			needclose++;
-		else
+		} else {
 			for (ns = 0; ns < statp->nscount; ns++) {
 				if (statp->nsaddr_list[ns].sin_family &&
 				    !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
@@ -445,6 +430,7 @@
 					break;
 				}
 			}
+		}
 		if (needclose) {
 			res_nclose(statp);
 			EXT(statp).nscount = 0;
@@ -485,7 +471,7 @@
 		nstime = EXT(statp).nstimes[0];
 		for (ns = 0; ns < lastns; ns++) {
 			if (EXT(statp).ext != NULL)
-                                EXT(statp).ext->nsaddrs[ns] =
+				EXT(statp).ext->nsaddrs[ns] =
 					EXT(statp).ext->nsaddrs[ns + 1];
 			statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
 			EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
@@ -502,13 +488,24 @@
 	 * Send request, RETRY times, or until successful.
 	 */
 	for (try = 0; try < statp->retry; try++) {
+	    struct __res_stats stats[MAXNS + 1];
+	    struct __res_params params;
+	    int revision_id = _resolv_cache_get_resolver_stats(statp->netid, &params, stats);
+	    bool usable_servers[MAXNS + 1];
+	    _res_stats_get_usable_servers(&params, stats, statp->nscount, usable_servers);
+
 	    for (ns = 0; ns < statp->nscount; ns++) {
+		if (!usable_servers[ns]) continue;
 		struct sockaddr *nsap;
 		int nsaplen;
+		time_t now = 0;
+		int rcode = RCODE_INTERNAL_ERROR;
+		int delay = 0;
 		nsap = get_nsaddr(statp, (size_t)ns);
 		nsaplen = get_salen(nsap);
 		statp->_flags &= ~RES_F_LASTMASK;
 		statp->_flags |= (ns << RES_F_LASTSHIFT);
+
  same_ns:
 		if (statp->qhook) {
 			int done = 0, loops = 0;
@@ -552,7 +549,12 @@
 			try = statp->retry;
 
 			n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
-				    ns);
+				    ns, &now, &rcode, &delay);
+
+			struct __res_sample sample;
+			_res_stats_set_sample(&sample, now, rcode, delay);
+			_resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns,
+				&sample, params.max_samples);
 
 			if (DBG) {
 				__libc_format_log(ANDROID_LOG_DEBUG, "libc",
@@ -571,7 +573,13 @@
 			}
 
 			n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
-				    ns, &v_circuit, &gotsomewhere);
+				    ns, &v_circuit, &gotsomewhere, &now, &rcode, &delay);
+
+			struct __res_sample sample;
+			_res_stats_set_sample(&sample, now, rcode, delay);
+			_resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns,
+				&sample, params.max_samples);
+
 			if (DBG) {
 				__libc_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n);
 			}
@@ -582,7 +590,7 @@
 				goto next_ns;
 			if (DBG) {
 				__libc_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n",
-                                                  time(NULL));
+						  time(NULL));
 			}
 			if (v_circuit)
 				goto same_ns;
@@ -599,12 +607,10 @@
 			(stdout, "%s", ""),
 			ans, (resplen > anssiz) ? anssiz : resplen);
 
-#if USE_RESOLV_CACHE
-                if (cache_status == RESOLV_CACHE_NOTFOUND) {
-                    _resolv_cache_add(statp->netid, buf, buflen,
-                                      ans, resplen);
-                }
-#endif
+		if (cache_status == RESOLV_CACHE_NOTFOUND) {
+		    _resolv_cache_add(statp->netid, buf, buflen,
+				      ans, resplen);
+		}
 		/*
 		 * If we have temporarily opened a virtual circuit,
 		 * or if we haven't been asked to keep a socket open,
@@ -656,15 +662,12 @@
 	} else
 		errno = terrno;
 
-#if USE_RESOLV_CACHE
-        _resolv_cache_query_failed(statp->netid, buf, buflen);
-#endif
+	_resolv_cache_query_failed(statp->netid, buf, buflen);
 
 	return (-1);
  fail:
-#if USE_RESOLV_CACHE
+
 	_resolv_cache_query_failed(statp->netid, buf, buflen);
-#endif
 	res_nclose(statp);
 	return (-1);
 }
@@ -735,8 +738,11 @@
 static int
 send_vc(res_state statp,
 	const u_char *buf, int buflen, u_char *ans, int anssiz,
-	int *terrno, int ns)
+	int *terrno, int ns, time_t* at, int* rcode, int* delay)
 {
+	*at = 0;
+	*rcode = RCODE_INTERNAL_ERROR;
+	*delay = 0;
 	const HEADER *hp = (const HEADER *)(const void *)buf;
 	HEADER *anhp = (HEADER *)(void *)ans;
 	struct sockaddr *nsap;
@@ -758,6 +764,8 @@
  same_ns:
 	truncating = 0;
 
+	struct timespec now = evNowTime();
+
 	/* Are we still talking to whom we want to talk to? */
 	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
 		struct sockaddr_storage peer;
@@ -800,7 +808,7 @@
 		}
 		if (statp->_mark != MARK_UNSET) {
 			if (setsockopt(statp->_vcsock, SOL_SOCKET,
-				        SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) {
+				    SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) {
 				*terrno = errno;
 				Perror(statp, stderr, "setsockopt", errno);
 				return -1;
@@ -820,6 +828,15 @@
 			Aerror(statp, stderr, "connect/vc", errno, nsap,
 			    nsaplen);
 			res_nclose(statp);
+			/*
+			 * The way connect_with_timeout() is implemented prevents us from reliably
+			 * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
+			 * currently both cases are handled in the same way, there is no need to
+			 * change this (yet). If we ever need to reliably distinguish between these
+			 * cases, both connect_with_timeout() and retrying_select() need to be
+			 * modified, though.
+			 */
+			*rcode = RCODE_TIMEOUT;
 			return (0);
 		}
 		statp->_flags |= RES_F_VC;
@@ -900,6 +917,10 @@
 		res_nclose(statp);
 		return (0);
 	}
+
+	struct timespec done = evNowTime();
+	*at = done.tv_sec;
+
 	if (truncating) {
 		/*
 		 * Flush rest of answer so connection stays in synch.
@@ -936,6 +957,10 @@
 	 * All is well, or the error is fatal.  Signal that the
 	 * next nameserver ought not be tried.
 	 */
+	if (resplen > 0) {
+	    *delay = _res_stats_calculate_rtt(&done, &now);
+	    *rcode = anhp->rcode;
+	}
 	return (resplen);
 }
 
@@ -952,8 +977,8 @@
 
 	res = __connect(sock, nsap, salen);
 	if (res < 0 && errno != EINPROGRESS) {
-                res = -1;
-                goto done;
+		res = -1;
+		goto done;
 	}
 	if (res != 0) {
 		now = evNowTime();
@@ -965,7 +990,7 @@
 
 		res = retrying_select(sock, &rset, &wset, &finish);
 		if (res <= 0) {
-                        res = -1;
+			res = -1;
 		}
 	}
 done:
@@ -987,7 +1012,7 @@
 
 retry:
 	if (DBG) {
-		__libc_format_log(ANDROID_LOG_DEBUG, "libc", "  %d retying_select\n", sock);
+		__libc_format_log(ANDROID_LOG_DEBUG, "libc", "  %d retrying_select\n", sock);
 	}
 
 	now = evNowTime();
@@ -1042,17 +1067,20 @@
 	return n;
 }
 
-
 static int
 send_dg(res_state statp,
 	const u_char *buf, int buflen, u_char *ans, int anssiz,
-	int *terrno, int ns, int *v_circuit, int *gotsomewhere)
+	int *terrno, int ns, int *v_circuit, int *gotsomewhere,
+	time_t *at, int *rcode, int* delay)
 {
+	*at = 0;
+	*rcode = RCODE_INTERNAL_ERROR;
+	*delay = 0;
 	const HEADER *hp = (const HEADER *)(const void *)buf;
 	HEADER *anhp = (HEADER *)(void *)ans;
 	const struct sockaddr *nsap;
 	int nsaplen;
-	struct timespec now, timeout, finish;
+	struct timespec now, timeout, finish, done;
 	fd_set dsmask;
 	struct sockaddr_storage from;
 	socklen_t fromlen;
@@ -1145,6 +1173,7 @@
 	n = retrying_select(s, &dsmask, NULL, &finish);
 
 	if (n == 0) {
+		*rcode = RCODE_TIMEOUT;
 		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
 		*gotsomewhere = 1;
 		return (0);
@@ -1239,6 +1268,9 @@
 			ans, (resplen > anssiz) ? anssiz : resplen);
 		goto retry;;
 	}
+	done = evNowTime();
+	*at = done.tv_sec;
+	*delay = _res_stats_calculate_rtt(&done, &now);
 	if (anhp->rcode == SERVFAIL ||
 	    anhp->rcode == NOTIMP ||
 	    anhp->rcode == REFUSED) {
@@ -1247,8 +1279,10 @@
 			ans, (resplen > anssiz) ? anssiz : resplen);
 		res_nclose(statp);
 		/* don't retry if called from dig */
-		if (!statp->pfcode)
+		if (!statp->pfcode) {
+			*rcode = anhp->rcode;
 			return (0);
+		}
 	}
 	if (!(statp->options & RES_IGNTC) && anhp->tc) {
 		/*
@@ -1265,6 +1299,9 @@
 	 * All is well, or the error is fatal.  Signal that the
 	 * next nameserver ought not be tried.
 	 */
+	if (resplen > 0) {
+		*rcode = anhp->rcode;
+	}
 	return (resplen);
 }
 
diff --git a/libc/dns/resolv/res_stats.c b/libc/dns/resolv/res_stats.c
new file mode 100644
index 0000000..5cc592e
--- /dev/null
+++ b/libc/dns/resolv/res_stats.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdbool.h>
+#include <arpa/nameser.h>
+#include <string.h>
+
+#include "resolv_stats.h"
+#include "private/libc_logging.h"
+#include "isc/eventlib.h"
+
+#define DBG 0
+
+/* Calculate the round-trip-time from start time t0 and end time t1. */
+int
+_res_stats_calculate_rtt(const struct timespec* t1, const struct timespec* t0) {
+    // Divide ns by one million to get ms, multiply s by thousand to get ms (obvious)
+    long ms0 = t0->tv_sec * 1000 + t0->tv_nsec / 1000000;
+    long ms1 = t1->tv_sec * 1000 + t1->tv_nsec / 1000000;
+    return (int) (ms1 - ms0);
+}
+
+/* Create a sample for calculating server reachability statistics. */
+void
+_res_stats_set_sample(struct __res_sample* sample, time_t now, int rcode, int rtt)
+{
+    if (DBG) {
+        __libc_format_log(ANDROID_LOG_INFO, "libc", "rcode = %d, sec = %d", rcode, rtt);
+    }
+    sample->at = now;
+    sample->rcode = rcode;
+    sample->rtt = rtt;
+}
+
+/* Clears all stored samples for the given server. */
+void
+_res_stats_clear_samples(struct __res_stats* stats)
+{
+    stats->sample_count = stats->sample_next = 0;
+}
+
+/* Aggregates the reachability statistics for the given server based on on the stored samples. */
+void
+_res_stats_aggregate(struct __res_stats* stats, int* successes, int* errors, int* timeouts,
+             int* internal_errors, int* rtt_avg, time_t* last_sample_time)
+{
+    int s = 0;   // successes
+    int e = 0;   // errors
+    int t = 0;   // timouts
+    int ie = 0;  // internal errors
+    long rtt_sum = 0;
+    time_t last = 0;
+    int rtt_count = 0;
+    for (int i = 0 ; i < stats->sample_count ; ++i) {
+        // Treat everything as an error that the code in send_dg() already considers a
+        // rejection by the server, i.e. SERVFAIL, NOTIMP and REFUSED. Assume that NXDOMAIN
+        // and NOTAUTH can actually occur for user queries. NOERROR with empty answer section
+        // is not treated as an error here either. FORMERR seems to sometimes be returned by
+        // some versions of BIND in response to DNSSEC or EDNS0. Whether to treat such responses
+        // as an indication of a broken server is unclear, though. For now treat such responses,
+        // as well as unknown codes as errors.
+        switch (stats->samples[i].rcode) {
+        case NOERROR:
+        case NOTAUTH:
+        case NXDOMAIN:
+            ++s;
+            rtt_sum += stats->samples[i].rtt;
+            ++rtt_count;
+            break;
+        case RCODE_TIMEOUT:
+            ++t;
+            break;
+        case RCODE_INTERNAL_ERROR:
+            ++ie;
+            break;
+        case SERVFAIL:
+        case NOTIMP:
+        case REFUSED:
+        default:
+            ++e;
+            break;
+        }
+    }
+    *successes = s;
+    *errors = e;
+    *timeouts = t;
+    *internal_errors = ie;
+    /* If there was at least one successful sample, calculate average RTT. */
+    if (rtt_count) {
+        *rtt_avg = rtt_sum / rtt_count;
+    } else {
+        *rtt_avg = -1;
+    }
+    /* If we had at least one sample, populate last sample time. */
+    if (stats->sample_count > 0) {
+        if (stats->sample_next > 0) {
+            last = stats->samples[stats->sample_next - 1].at;
+        } else {
+            last = stats->samples[stats->sample_count - 1].at;
+        }
+    }
+    *last_sample_time = last;
+}
+
+bool
+_res_stats_usable_server(const struct __res_params* params, struct __res_stats* stats) {
+    int successes = -1;
+    int errors = -1;
+    int timeouts = -1;
+    int internal_errors = -1;
+    int rtt_avg = -1;
+    time_t last_sample_time = 0;
+    _res_stats_aggregate(stats, &successes, &errors, &timeouts, &internal_errors, &rtt_avg,
+            &last_sample_time);
+    if (successes >= 0 && errors >= 0 && timeouts >= 0) {
+        int total = successes + errors + timeouts;
+        if (DBG) {
+            __libc_format_log(ANDROID_LOG_DEBUG, "libc", "NS stats: S %d + E %d + T %d + I %d "
+                 "= %d, rtt = %d, min_samples = %d\n", successes, errors, timeouts, internal_errors,
+                 total, rtt_avg, params->min_samples);
+        }
+        if (total >= params->min_samples && (errors > 0 || timeouts > 0)) {
+            int success_rate = successes * 100 / total;
+            if (DBG) {
+                __libc_format_log(ANDROID_LOG_DEBUG, "libc", "success rate %d%%\n", success_rate);
+            }
+            if (success_rate < params->success_threshold) {
+                // evNowTime() is used here instead of time() to stay consistent with the rest of
+                // the code base
+                time_t now = evNowTime().tv_sec;
+                if (now - last_sample_time > params->sample_validity) {
+                    // Note: It might be worth considering to expire old servers after their expiry
+                    // date has been reached, however the code for returning the ring buffer to its
+                    // previous non-circular state would induce additional complexity.
+                    if (DBG) {
+                        __libc_format_log(ANDROID_LOG_INFO, "libc",
+                            "samples stale, retrying server\n");
+                    }
+                    _res_stats_clear_samples(stats);
+                } else {
+                    if (DBG) {
+                        __libc_format_log(ANDROID_LOG_INFO, "libc",
+                            "too many resolution errors, ignoring server\n");
+                    }
+                    return 0;
+                }
+            }
+        }
+    }
+    return 1;
+}
+
+void
+_res_stats_get_usable_servers(const struct __res_params* params, struct __res_stats stats[],
+        int nscount, bool usable_servers[]) {
+    unsigned usable_servers_found = 0;
+    for (int ns = 0; ns < nscount; ns++) {
+        bool usable = _res_stats_usable_server(params, &stats[ns]);
+        if (usable) {
+            ++usable_servers_found;
+        }
+        usable_servers[ns] = usable;
+    }
+    // If there are no usable servers, consider all of them usable.
+    // TODO: Explore other possibilities, such as enabling only the best N servers, etc.
+    if (usable_servers_found == 0) {
+        for (int ns = 0; ns < nscount; ns++) {
+            usable_servers[ns] = true;
+        }
+    }
+}
diff --git a/libc/libc.arm.brillo.map b/libc/libc.arm.brillo.map
index 2c0ab15..8db393f 100644
--- a/libc/libc.arm.brillo.map
+++ b/libc/libc.arm.brillo.map
@@ -1415,7 +1415,7 @@
     __swrite; # arm x86 mips
     __swsetup; # arm x86 mips
     __truncdfsf2; # arm
-    __udivdi3; # arm mips
+    __udivdi3; # arm x86 mips
     __udivsi3; # arm
     __unorddf2; # arm
     __unordsf2; # arm
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index c22535d..e2d36d1 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1426,7 +1426,7 @@
     __swrite; # arm x86 mips
     __swsetup; # arm x86 mips
     __truncdfsf2; # arm
-    __udivdi3; # arm mips
+    __udivdi3; # arm x86 mips
     __udivsi3; # arm
     __unorddf2; # arm
     __unordsf2; # arm
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index c000fb1..f7dad58 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -207,7 +207,6 @@
     __timer_getoverrun; # arm x86 mips
     __timer_gettime; # arm x86 mips
     __timer_settime; # arm x86 mips
-    __udivdi3; # x86
     __umask_chk;
     __vsnprintf_chk;
     __vsprintf_chk;
@@ -1452,7 +1451,7 @@
     __swrite; # arm x86 mips
     __swsetup; # arm x86 mips
     __truncdfsf2; # arm
-    __udivdi3; # arm mips
+    __udivdi3; # arm x86 mips
     __udivsi3; # arm
     __umoddi3; # x86 mips
     __unorddf2; # arm
diff --git a/libc/libc.mips.brillo.map b/libc/libc.mips.brillo.map
index 8e5fdf4..f441206 100644
--- a/libc/libc.mips.brillo.map
+++ b/libc/libc.mips.brillo.map
@@ -1275,7 +1275,7 @@
     __swbuf; # arm x86 mips
     __swrite; # arm x86 mips
     __swsetup; # arm x86 mips
-    __udivdi3; # arm mips
+    __udivdi3; # arm x86 mips
     __umoddi3; # x86 mips
     _fwalk; # arm x86 mips
     android_getaddrinfofornet;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index d30ead8..b5c4c7b 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1286,7 +1286,7 @@
     __swbuf; # arm x86 mips
     __swrite; # arm x86 mips
     __swsetup; # arm x86 mips
-    __udivdi3; # arm mips
+    __udivdi3; # arm x86 mips
     __umoddi3; # x86 mips
     __wait4; # arm x86 mips nobrillo
     _fwalk; # arm x86 mips
diff --git a/libc/libc.x86.brillo.map b/libc/libc.x86.brillo.map
index 7ac0976..fa79567 100644
--- a/libc/libc.x86.brillo.map
+++ b/libc/libc.x86.brillo.map
@@ -203,7 +203,6 @@
     __timer_getoverrun; # arm x86 mips
     __timer_gettime; # arm x86 mips
     __timer_settime; # arm x86 mips
-    __udivdi3; # x86
     __umask_chk;
     __vsnprintf_chk;
     __vsprintf_chk;
@@ -1275,6 +1274,7 @@
     __swbuf; # arm x86 mips
     __swrite; # arm x86 mips
     __swsetup; # arm x86 mips
+    __udivdi3; # arm x86 mips
     __umoddi3; # x86 mips
     _fwalk; # arm x86 mips
     android_getaddrinfofornet;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 11fb710..3b4da4e 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -203,7 +203,6 @@
     __timer_getoverrun; # arm x86 mips
     __timer_gettime; # arm x86 mips
     __timer_settime; # arm x86 mips
-    __udivdi3; # x86
     __umask_chk;
     __vsnprintf_chk;
     __vsprintf_chk;
@@ -1286,6 +1285,7 @@
     __swbuf; # arm x86 mips
     __swrite; # arm x86 mips
     __swsetup; # arm x86 mips
+    __udivdi3; # arm x86 mips
     __umoddi3; # x86 mips
     __wait4; # arm x86 mips nobrillo
     _fwalk; # arm x86 mips
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index 4586fda3..ded618c 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -333,9 +333,9 @@
   size_t value;
   bool value_set;
   PropertyParser parser(property_str);
-  bool found = false;
   bool valid = true;
   while (valid && parser.Get(&property, &value, &value_set)) {
+    bool found = false;
     for (size_t i = 0; i < sizeof(features)/sizeof(Feature); i++) {
       if (property == features[i].name) {
         if (features[i].option == 0 && features[i].combo_option) {
diff --git a/libc/malloc_debug/FreeTrackData.cpp b/libc/malloc_debug/FreeTrackData.cpp
index 3ac54bf..ed41981 100644
--- a/libc/malloc_debug/FreeTrackData.cpp
+++ b/libc/malloc_debug/FreeTrackData.cpp
@@ -67,18 +67,25 @@
                                   const void* pointer) {
   ScopedDisableDebugCalls disable;
 
-  const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
-  size_t bytes = header->usable_size;
-  bytes = (bytes < debug.config().fill_on_free_bytes) ? bytes : debug.config().fill_on_free_bytes;
-  while (bytes > 0) {
-    size_t bytes_to_cmp = (bytes < cmp_mem_.size()) ? bytes : cmp_mem_.size();
-    if (memcmp(memory, cmp_mem_.data(), bytes_to_cmp) != 0) {
-      LogFreeError(debug, header, reinterpret_cast<const uint8_t*>(pointer));
-      break;
+  if (header->tag != DEBUG_FREE_TAG) {
+    error_log(LOG_DIVIDER);
+    error_log("+++ ALLOCATION %p HAS CORRUPTED HEADER TAG 0x%x AFTER FREE", pointer, header->tag);
+    error_log(LOG_DIVIDER);
+  } else {
+    const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
+    size_t bytes = header->usable_size;
+    bytes = (bytes < debug.config().fill_on_free_bytes) ? bytes : debug.config().fill_on_free_bytes;
+    while (bytes > 0) {
+      size_t bytes_to_cmp = (bytes < cmp_mem_.size()) ? bytes : cmp_mem_.size();
+      if (memcmp(memory, cmp_mem_.data(), bytes_to_cmp) != 0) {
+        LogFreeError(debug, header, reinterpret_cast<const uint8_t*>(pointer));
+        break;
+      }
+      bytes -= bytes_to_cmp;
+      memory = &memory[bytes_to_cmp];
     }
-    bytes -= bytes_to_cmp;
-    memory = &memory[bytes_to_cmp];
   }
+
   auto back_iter = backtraces_.find(header);
   if (back_iter != backtraces_.end()) {
     g_dispatch->free(reinterpret_cast<void*>(back_iter->second));
@@ -98,7 +105,6 @@
     list_.pop_back();
   }
 
-  // Only log the free backtrace if we are using the free track feature.
   if (backtrace_num_frames_ > 0) {
     BacktraceHeader* back_header = reinterpret_cast<BacktraceHeader*>(
       g_dispatch->malloc(sizeof(BacktraceHeader) + backtrace_num_frames_ * sizeof(uintptr_t)));
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 568192d..1ee7689 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -112,6 +112,7 @@
     );
   });
 }
+
 static void LogTagError(const Header* header, const void* pointer, const char* name) {
   ScopedDisableDebugCalls disable;
 
@@ -145,7 +146,7 @@
     return nullptr;
   }
   header->usable_size -= g_debug->pointer_offset() +
-      reinterpret_cast<uintptr_t>(orig_pointer) - reinterpret_cast<uintptr_t>(header);
+      reinterpret_cast<uintptr_t>(header) - reinterpret_cast<uintptr_t>(orig_pointer);
 
   if (g_debug->config().options & FRONT_GUARD) {
     uint8_t* guard = g_debug->GetFrontGuard(header);
@@ -326,8 +327,9 @@
 
   void* free_pointer = pointer;
   size_t bytes;
+  Header* header;
   if (g_debug->need_header()) {
-    Header* header = g_debug->GetHeader(pointer);
+    header = g_debug->GetHeader(pointer);
     if (header->tag != DEBUG_TAG) {
       LogTagError(header, pointer, "free");
       return;
@@ -353,13 +355,6 @@
       }
       g_debug->track->Remove(header, backtrace_found);
     }
-
-    if (g_debug->config().options & FREE_TRACK) {
-      g_debug->free_track->Add(*g_debug, header);
-
-      // Do not free this pointer just yet.
-      free_pointer = nullptr;
-    }
     header->tag = DEBUG_FREE_TAG;
 
     bytes = header->usable_size;
@@ -373,7 +368,16 @@
     memset(pointer, g_debug->config().fill_free_value, bytes);
   }
 
-  g_dispatch->free(free_pointer);
+  if (g_debug->config().options & FREE_TRACK) {
+    // Do not add the allocation until we are done modifying the pointer
+    // itself. This avoids a race if a lot of threads are all doing
+    // frees at the same time and we wind up trying to really free this
+    // pointer from another thread, while still trying to free it in
+    // this function.
+    g_debug->free_track->Add(*g_debug, header);
+  } else {
+    g_dispatch->free(free_pointer);
+  }
 }
 
 void* debug_memalign(size_t alignment, size_t bytes) {
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index a6cea98..85d5cb5 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -124,6 +124,14 @@
   ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugConfigTest, good_option_and_bad_option) {
+  ASSERT_FALSE(InitConfig("backtrace unknown_option"));
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string log_msg("6 malloc_debug malloc_testing: unknown option unknown_option\n");
+  ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
+}
+
 TEST_F(MallocDebugConfigTest, unparseable_number) {
   ASSERT_FALSE(InitConfig("backtrace=XXX"));
 
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 2503981..b6bf7bc 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <thread>
 #include <vector>
 #include <utility>
 
@@ -898,6 +899,53 @@
   ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugTest, free_track_header_tag_corrupted) {
+  Init("free_track=100 free_track_backtrace_num_frames=0");
+
+  uint8_t* pointer = reinterpret_cast<uint8_t*>(debug_malloc(100));
+  ASSERT_TRUE(pointer != nullptr);
+  memset(pointer, 0, 100);
+  debug_free(pointer);
+
+  pointer[-get_tag_offset()] = 0x00;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+
+  debug_finalize();
+  initialized = false;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string expected_log(DIVIDER);
+  expected_log += android::base::StringPrintf(
+      "6 malloc_debug +++ ALLOCATION %p HAS CORRUPTED HEADER TAG 0x1cc7dc00 AFTER FREE\n",
+      pointer);
+  expected_log += DIVIDER;
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, free_track_multiple_thread) {
+  Init("free_track=10 free_track_backtrace_num_frames=0");
+
+  std::vector<std::thread*> threads(1000);
+  for (size_t i = 0; i < threads.size(); i++) {
+    threads[i] = new std::thread([](){
+      for (size_t j = 0; j < 100; j++) {
+        void* mem = debug_malloc(100);
+        write(0, mem, 0);
+        debug_free(mem);
+      }
+    });
+  }
+  for (size_t i = 0; i < threads.size(); i++) {
+    threads[i]->join();
+    delete threads[i];
+  }
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
 TEST_F(MallocDebugTest, get_malloc_leak_info_invalid) {
   Init("fill");
 
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index bcb05a0..b45c0c3 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -49,4 +49,9 @@
 __LIBC_HIDDEN__ void __libc_init_setjmp_cookie(libc_globals* globals, KernelArgumentBlock& args);
 __LIBC_HIDDEN__ void __libc_init_vdso(libc_globals* globals, KernelArgumentBlock& args);
 
+#if defined(__i386__)
+__LIBC_HIDDEN__ extern void* __libc_sysinfo;
+__LIBC_HIDDEN__ void __libc_init_sysinfo(KernelArgumentBlock& args);
+#endif
+
 #endif
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 4d0afe2..f7785d6 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -166,9 +166,20 @@
 
 x86_registers = [ "ebx", "ecx", "edx", "esi", "edi", "ebp" ]
 
+x86_call_prepare = """\
+
+    call    __kernel_syscall
+    pushl   %eax
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset eax, 0
+
+"""
+
 x86_call = """\
     movl    $%(__NR_name)s, %%eax
-    int     $0x80
+    call    *(%%esp)
+    addl    $4, %%esp
+
     cmpl    $-MAX_ERRNO, %%eax
     jb      1f
     negl    %%eax
@@ -311,7 +322,7 @@
     result     = syscall_stub_header % syscall
 
     numparams = count_generic_param_registers(syscall["params"])
-    stack_bias = numparams*4 + 4
+    stack_bias = numparams*4 + 8
     offset = 0
     mov_result = ""
     first_push = True
@@ -327,6 +338,7 @@
         mov_result += "    mov     %d(%%esp), %%%s\n" % (stack_bias+offset, register)
         offset += 4
 
+    result += x86_call_prepare
     result += mov_result
     result += x86_call % syscall
 
@@ -352,7 +364,9 @@
     result += "    pushl   %ecx\n"
     result += "    .cfi_adjust_cfa_offset 4\n"
     result += "    .cfi_rel_offset ecx, 0\n"
-    stack_bias = 12
+    stack_bias = 16
+
+    result += x86_call_prepare
 
     # set the call id (%ebx)
     result += "    mov     $%d, %%ebx\n" % syscall["socketcall_id"]
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map
index 9d97bd0..2821509 100644
--- a/libdl/libdl.arm.map
+++ b/libdl/libdl.arm.map
@@ -16,8 +16,6 @@
 
 LIBC_N {
   global:
-    android_init_namespaces;
-    android_create_namespace;
     dlvsym;
 } LIBC;
 
@@ -28,4 +26,6 @@
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
+    android_init_namespaces;
+    android_create_namespace;
 } LIBC_N;
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
index 0a5ac97..f21859c 100644
--- a/libdl/libdl.arm64.map
+++ b/libdl/libdl.arm64.map
@@ -15,8 +15,6 @@
 
 LIBC_N {
   global:
-    android_init_namespaces;
-    android_create_namespace;
     dlvsym;
 } LIBC;
 
@@ -27,4 +25,6 @@
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
+    android_init_namespaces;
+    android_create_namespace;
 } LIBC_N;
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index 78ac707..962692e 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -30,8 +30,6 @@
 
 LIBC_N {
   global:
-    android_init_namespaces;
-    android_create_namespace;
     dlvsym;
 } LIBC;
 
@@ -42,4 +40,6 @@
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
+    android_init_namespaces;
+    android_create_namespace;
 } LIBC_N;
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
index 0a5ac97..f21859c 100644
--- a/libdl/libdl.mips.map
+++ b/libdl/libdl.mips.map
@@ -15,8 +15,6 @@
 
 LIBC_N {
   global:
-    android_init_namespaces;
-    android_create_namespace;
     dlvsym;
 } LIBC;
 
@@ -27,4 +25,6 @@
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
+    android_init_namespaces;
+    android_create_namespace;
 } LIBC_N;
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
index 0a5ac97..f21859c 100644
--- a/libdl/libdl.mips64.map
+++ b/libdl/libdl.mips64.map
@@ -15,8 +15,6 @@
 
 LIBC_N {
   global:
-    android_init_namespaces;
-    android_create_namespace;
     dlvsym;
 } LIBC;
 
@@ -27,4 +25,6 @@
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
+    android_init_namespaces;
+    android_create_namespace;
 } LIBC_N;
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
index 0a5ac97..f21859c 100644
--- a/libdl/libdl.x86.map
+++ b/libdl/libdl.x86.map
@@ -15,8 +15,6 @@
 
 LIBC_N {
   global:
-    android_init_namespaces;
-    android_create_namespace;
     dlvsym;
 } LIBC;
 
@@ -27,4 +25,6 @@
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
+    android_init_namespaces;
+    android_create_namespace;
 } LIBC_N;
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
index 0a5ac97..f21859c 100644
--- a/libdl/libdl.x86_64.map
+++ b/libdl/libdl.x86_64.map
@@ -15,8 +15,6 @@
 
 LIBC_N {
   global:
-    android_init_namespaces;
-    android_create_namespace;
     dlvsym;
 } LIBC;
 
@@ -27,4 +25,6 @@
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
+    android_init_namespaces;
+    android_create_namespace;
 } LIBC_N;
diff --git a/linker/Android.mk b/linker/Android.mk
index 1620888..4a4ca5c 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -11,6 +11,7 @@
     linker_allocator.cpp \
     linker_block_allocator.cpp \
     linker_dlwarning.cpp \
+    linker_gdb_support.cpp \
     linker_libc_support.c \
     linker_mapped_file_fragment.cpp \
     linker_memory.cpp \
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 670d1ea..d4c7928 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -27,6 +27,7 @@
  */
 
 #include "linker.h"
+#include "linker_gdb_support.h"
 
 #include <errno.h>
 #include <inttypes.h>
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 64bf9e0..ce9fbe6 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -69,7 +69,7 @@
 static void* dlopen_ext(const char* filename, int flags,
                         const android_dlextinfo* extinfo, void* caller_addr) {
   ScopedPthreadMutexLocker locker(&g_dl_mutex);
-  soinfo* result = do_dlopen(filename, flags, extinfo, caller_addr);
+  void* result = do_dlopen(filename, flags, extinfo, caller_addr);
   if (result == nullptr) {
     __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
     return nullptr;
@@ -87,8 +87,6 @@
   return dlopen_ext(filename, flags, nullptr, caller_addr);
 }
 
-extern android_namespace_t* g_anonymous_namespace;
-
 void* dlsym_impl(void* handle, const char* symbol, const char* version, void* caller_addr) {
   ScopedPthreadMutexLocker locker(&g_dl_mutex);
   void* result;
@@ -117,9 +115,11 @@
 
 int dlclose(void* handle) {
   ScopedPthreadMutexLocker locker(&g_dl_mutex);
-  do_dlclose(reinterpret_cast<soinfo*>(handle));
-  // dlclose has no defined errors.
-  return 0;
+  int result = do_dlclose(handle);
+  if (result != 0) {
+    __bionic_format_dlerror("dlclose failed", linker_get_error_buffer());
+  }
+  return result;
 }
 
 int dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
@@ -270,6 +270,7 @@
     __libdl_info->local_group_root_ = __libdl_info;
     __libdl_info->soname_ = "libdl.so";
     __libdl_info->target_sdk_version_ = __ANDROID_API__;
+    __libdl_info->generate_handle();
 #if defined(__work_around_b_24465209__)
     strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_));
 #endif
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 88386b0..092e831 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -43,7 +43,7 @@
     return *this;
   }
 
-  T* operator*() {
+  T* const operator*() {
     return entry_->element;
   }
 
@@ -190,15 +190,15 @@
     return nullptr;
   }
 
-  iterator begin() {
+  iterator begin() const {
     return iterator(head_);
   }
 
-  iterator end() {
+  iterator end() const {
     return iterator(nullptr);
   }
 
-  iterator find(T* value) {
+  iterator find(T* value) const {
     for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
       if (e->element == value) {
         return iterator(e);
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 86b1093..d6ee8cf 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -44,6 +44,7 @@
 #include <vector>
 
 // Private C library headers.
+#include "private/bionic_globals.h"
 #include "private/bionic_tls.h"
 #include "private/KernelArgumentBlock.h"
 #include "private/ScopedPthreadMutexLocker.h"
@@ -51,6 +52,7 @@
 
 #include "linker.h"
 #include "linker_block_allocator.h"
+#include "linker_gdb_support.h"
 #include "linker_debug.h"
 #include "linker_dlwarning.h"
 #include "linker_sleb128.h"
@@ -65,6 +67,8 @@
 extern void __libc_init_globals(KernelArgumentBlock&);
 extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
 
+extern "C" void _start();
+
 // Override macros to use C++ style casts.
 #undef ELF_ST_TYPE
 #define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
@@ -100,7 +104,24 @@
     permitted_paths_ = permitted_paths;
   }
 
-  soinfo::soinfo_list_t& soinfo_list() { return soinfo_list_; }
+  void add_soinfo(soinfo* si) {
+    soinfo_list_.push_back(si);
+  }
+
+  void add_soinfos(const soinfo::soinfo_list_t& soinfos) {
+    for (auto si : soinfos) {
+      add_soinfo(si);
+      si->add_secondary_namespace(this);
+    }
+  }
+
+  void remove_soinfo(soinfo* si) {
+    soinfo_list_.remove_if([&](soinfo* candidate) {
+      return si == candidate;
+    });
+  }
+
+  const soinfo::soinfo_list_t& soinfo_list() const { return soinfo_list_; }
 
   // For isolated namespaces - checks if the file is on the search path;
   // always returns true for not isolated namespace.
@@ -118,7 +139,8 @@
 };
 
 android_namespace_t g_default_namespace;
-android_namespace_t* g_anonymous_namespace = &g_default_namespace;
+static std::unordered_map<uintptr_t, soinfo*> g_soinfo_handles_map;
+static android_namespace_t* g_anonymous_namespace = &g_default_namespace;
 
 static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf);
 
@@ -126,6 +148,7 @@
 static LinkerTypeAllocator<LinkedListEntry<soinfo>> g_soinfo_links_allocator;
 
 static LinkerTypeAllocator<android_namespace_t> g_namespace_allocator;
+static LinkerTypeAllocator<LinkedListEntry<android_namespace_t>> g_namespace_list_allocator;
 
 static soinfo* solist;
 static soinfo* sonext;
@@ -181,6 +204,8 @@
     "libbinder.so",
     "libcrypto.so",
     "libcutils.so",
+    "libexpat.so",
+    "libgui.so",
     "libmedia.so",
     "libnativehelper.so",
     "libskia.so",
@@ -272,95 +297,27 @@
   return sizeof(__linker_dl_err_buf);
 }
 
-// This function is an empty stub where GDB locates a breakpoint to get notified
-// about linker activity.
-extern "C"
-void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity();
+static void notify_gdb_of_load(soinfo* info) {
+  if (info->is_linker() || info->is_main_executable()) {
+    // gdb already knows about the linker and the main executable.
+    return;
+  }
 
-static pthread_mutex_t g__r_debug_mutex = PTHREAD_MUTEX_INITIALIZER;
-static r_debug _r_debug =
-    {1, nullptr, reinterpret_cast<uintptr_t>(&rtld_db_dlactivity), r_debug::RT_CONSISTENT, 0};
-
-static link_map* r_debug_tail = 0;
-
-static void insert_soinfo_into_debug_map(soinfo* info) {
-  // Copy the necessary fields into the debug structure.
   link_map* map = &(info->link_map_head);
+
   map->l_addr = info->load_bias;
   // link_map l_name field is not const.
   map->l_name = const_cast<char*>(info->get_realpath());
   map->l_ld = info->dynamic;
 
-  // Stick the new library at the end of the list.
-  // gdb tends to care more about libc than it does
-  // about leaf libraries, and ordering it this way
-  // reduces the back-and-forth over the wire.
-  if (r_debug_tail) {
-    r_debug_tail->l_next = map;
-    map->l_prev = r_debug_tail;
-    map->l_next = 0;
-  } else {
-    _r_debug.r_map = map;
-    map->l_prev = 0;
-    map->l_next = 0;
-  }
-  r_debug_tail = map;
-}
+  CHECK(map->l_name != nullptr);
+  CHECK(map->l_name[0] != '\0');
 
-static void remove_soinfo_from_debug_map(soinfo* info) {
-  link_map* map = &(info->link_map_head);
-
-  if (r_debug_tail == map) {
-    r_debug_tail = map->l_prev;
-  }
-
-  if (map->l_prev) {
-    map->l_prev->l_next = map->l_next;
-  }
-  if (map->l_next) {
-    map->l_next->l_prev = map->l_prev;
-  }
-}
-
-static void notify_gdb_of_load(soinfo* info) {
-  if (info->is_main_executable()) {
-    // GDB already knows about the main executable
-    return;
-  }
-
-  ScopedPthreadMutexLocker locker(&g__r_debug_mutex);
-
-  _r_debug.r_state = r_debug::RT_ADD;
-  rtld_db_dlactivity();
-
-  insert_soinfo_into_debug_map(info);
-
-  _r_debug.r_state = r_debug::RT_CONSISTENT;
-  rtld_db_dlactivity();
+  notify_gdb_of_load(map);
 }
 
 static void notify_gdb_of_unload(soinfo* info) {
-  if (info->is_main_executable()) {
-    // GDB already knows about the main executable
-    return;
-  }
-
-  ScopedPthreadMutexLocker locker(&g__r_debug_mutex);
-
-  _r_debug.r_state = r_debug::RT_DELETE;
-  rtld_db_dlactivity();
-
-  remove_soinfo_from_debug_map(info);
-
-  _r_debug.r_state = r_debug::RT_CONSISTENT;
-  rtld_db_dlactivity();
-}
-
-void notify_gdb_of_libraries() {
-  _r_debug.r_state = r_debug::RT_ADD;
-  rtld_db_dlactivity();
-  _r_debug.r_state = r_debug::RT_CONSISTENT;
-  rtld_db_dlactivity();
+  notify_gdb_of_unload(&(info->link_map_head));
 }
 
 bool android_namespace_t::is_accessible(const std::string& file) {
@@ -397,6 +354,14 @@
   g_soinfo_links_allocator.free(entry);
 }
 
+LinkedListEntry<android_namespace_t>* NamespaceListAllocator::alloc() {
+  return g_namespace_list_allocator.alloc();
+}
+
+void NamespaceListAllocator::free(LinkedListEntry<android_namespace_t>* entry) {
+  g_namespace_list_allocator.free(entry);
+}
+
 static soinfo* soinfo_alloc(android_namespace_t* ns, const char* name,
                             struct stat* file_stat, off64_t file_offset,
                             uint32_t rtld_flags) {
@@ -411,7 +376,8 @@
   sonext->next = si;
   sonext = si;
 
-  ns->soinfo_list().push_back(si);
+  si->generate_handle();
+  ns->add_soinfo(si);
 
   TRACE("name %s: allocated soinfo @ %p", name, si);
   return si;
@@ -459,11 +425,6 @@
     sonext = prev;
   }
 
-  // remove from the namespace
-  si->get_namespace()->soinfo_list().remove_if([&](soinfo* candidate) {
-    return si == candidate;
-  });
-
   si->~soinfo();
   g_soinfo_allocator.free(si);
 }
@@ -510,13 +471,21 @@
         }
 
         ZipArchiveHandle handle = nullptr;
+        void* cookie = nullptr;
+        auto zip_guard = make_scope_guard([&]() {
+          if (cookie != nullptr) {
+            EndIteration(cookie);
+          }
+          if (handle != nullptr) {
+            CloseArchive(handle);
+          }
+        });
         if (OpenArchive(resolved_path, &handle) != 0) {
           DL_WARN("Warning: unable to open zip archive: %s", resolved_path);
           continue;
         }
 
         // Check if zip-file has a dir with entry_path name
-        void* cookie = nullptr;
         std::string prefix_str = entry_path + "/";
         ZipString prefix(prefix_str.c_str());
 
@@ -537,13 +506,6 @@
           continue;
         }
 
-        auto zip_guard = make_scope_guard([&]() {
-          if (cookie != nullptr) {
-            EndIteration(cookie);
-          }
-          CloseArchive(handle);
-        });
-
         resolved_paths->push_back(std::string(resolved_path) + kZipFileSeparator + entry_path);
       }
     }
@@ -621,7 +583,7 @@
   std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
   __libc_format_buffer(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
   if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
-    PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
+    PRINT("readlink(\"%s\") failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
     return false;
   }
 
@@ -802,8 +764,8 @@
       ELF_ST_BIND(s->st_info) == STB_WEAK) {
     return s->st_shndx != SHN_UNDEF;
   } else if (ELF_ST_BIND(s->st_info) != STB_LOCAL) {
-    DL_WARN("unexpected ST_BIND value: %d for '%s' in '%s'",
-        ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath());
+    DL_WARN("unexpected ST_BIND value: %d for \"%s\" in \"%s\"",
+            ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath());
   }
 
   return false;
@@ -954,7 +916,11 @@
   }
 
   this->rtld_flags_ = rtld_flags;
-  this->namespace_ = ns;
+  this->primary_namespace_ = ns;
+}
+
+soinfo::~soinfo() {
+  g_soinfo_handles_map.erase(handle_);
 }
 
 static uint32_t calculate_elf_hash(const char* name) {
@@ -1110,6 +1076,7 @@
     g_soinfo_allocator.protect_all(protection);
     g_soinfo_links_allocator.protect_all(protection);
     g_namespace_allocator.protect_all(protection);
+    g_namespace_list_allocator.protect_all(protection);
   }
 
   static size_t ref_count_;
@@ -1391,21 +1358,21 @@
                                             void* handle) {
   SymbolName symbol_name(name);
 
-  soinfo::soinfo_list_t& soinfo_list = ns->soinfo_list();
-  soinfo::soinfo_list_t::iterator start = soinfo_list.begin();
+  auto& soinfo_list = ns->soinfo_list();
+  auto start = soinfo_list.begin();
 
   if (handle == RTLD_NEXT) {
     if (caller == nullptr) {
       return nullptr;
     } else {
-      soinfo::soinfo_list_t::iterator it = soinfo_list.find(caller);
+      auto it = soinfo_list.find(caller);
       CHECK (it != soinfo_list.end());
       start = ++it;
     }
   }
 
   const ElfW(Sym)* s = nullptr;
-  for (soinfo::soinfo_list_t::iterator it = start, end = soinfo_list.end(); it != end; ++it) {
+  for (auto it = start, end = soinfo_list.end(); it != end; ++it) {
     soinfo* si = *it;
     // Do not skip RTLD_LOCAL libraries in dlsym(RTLD_DEFAULT, ...)
     // if the library is opened by application with target api level <= 22
@@ -1525,6 +1492,7 @@
 
   if (OpenArchiveFd(fd, "", handle) != 0) {
     // invalid zip-file (?)
+    CloseArchive(handle);
     close(fd);
     return false;
   }
@@ -1548,7 +1516,7 @@
   }
 
   const char* const path = normalized_path.c_str();
-  TRACE("Trying zip file open from path '%s' -> normalized '%s'", input_path, path);
+  TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
 
   // Treat an '!/' separator inside a path as the separator between the name
   // of the zip file on disk and the subdirectory to search within it.
@@ -1711,7 +1679,7 @@
   if (get_application_target_sdk_version() <= 22) {
     const char* bname = basename(dt_needed);
     if (bname != dt_needed) {
-      DL_WARN("'%s' library has invalid DT_NEEDED entry '%s'", sopath, dt_needed);
+      DL_WARN("library \"%s\" has invalid DT_NEEDED entry \"%s\"", sopath, dt_needed);
       add_dlwarning(sopath, "invalid DT_NEEDED entry",  dt_needed);
     }
 
@@ -1785,7 +1753,7 @@
     if (si == nullptr) {
       si = g_public_namespace.find_if(predicate);
       if (si != nullptr) {
-        ns->soinfo_list().push_back(si);
+        ns->add_soinfo(si);
       }
     }
 
@@ -1973,7 +1941,7 @@
     });
 
     if (candidate != nullptr) {
-      ns->soinfo_list().push_back(candidate);
+      ns->add_soinfo(candidate);
       task->set_soinfo(candidate);
       return true;
     }
@@ -1981,7 +1949,7 @@
 
   // Library might still be loaded, the accurate detection
   // of this fact is done by load_library.
-  TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]",
+  TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]",
       task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
 
   if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags)) {
@@ -2221,7 +2189,7 @@
   }
 
   if (!root->can_unload()) {
-    TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_realpath());
+    TRACE("not unloading \"%s\" - the binary is flagged with NODELETE", root->get_realpath());
     return;
   }
 
@@ -2264,7 +2232,7 @@
           TRACE("deprecated (old format of soinfo): %s needs to unload %s",
               si->get_realpath(), library_name);
 
-          soinfo* needed = find_library(si->get_namespace(),
+          soinfo* needed = find_library(si->get_primary_namespace(),
                                         library_name, RTLD_NOLOAD, nullptr, nullptr);
 
           if (needed != nullptr) {
@@ -2301,8 +2269,8 @@
       soinfo_unload(si);
     }
   } else {
-    TRACE("not unloading '%s' group, decrementing ref_count to %zd",
-        root->get_realpath(), ref_count);
+    TRACE("not unloading \"%s\" group, decrementing ref_count to %zd",
+          root->get_realpath(), ref_count);
   }
 }
 
@@ -2314,6 +2282,10 @@
   return std::string(sym_name) + ", version " + sym_ver;
 }
 
+static android_namespace_t* get_caller_namespace(soinfo* caller) {
+  return caller != nullptr ? caller->get_primary_namespace() : g_anonymous_namespace;
+}
+
 void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
   // Use basic string manipulation calls to avoid snprintf.
   // snprintf indirectly calls pthread_getspecific to get the size of a buffer.
@@ -2341,7 +2313,7 @@
   parse_LD_LIBRARY_PATH(ld_library_path);
 }
 
-soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo,
+void* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo,
                   void* caller_addr) {
   soinfo* const caller = find_containing_library(caller_addr);
 
@@ -2350,7 +2322,7 @@
     return nullptr;
   }
 
-  android_namespace_t* ns = caller != nullptr ? caller->get_namespace() : g_anonymous_namespace;
+  android_namespace_t* ns = get_caller_namespace(caller);
 
   if (extinfo != nullptr) {
     if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
@@ -2385,9 +2357,10 @@
   soinfo* si = find_library(ns, name, flags, extinfo, caller);
   if (si != nullptr) {
     si->call_constructors();
+    return si->to_handle();
   }
 
-  return si;
+  return nullptr;
 }
 
 int do_dladdr(const void* addr, Dl_info* info) {
@@ -2413,6 +2386,19 @@
   return 1;
 }
 
+static soinfo* soinfo_from_handle(void* handle) {
+  if ((reinterpret_cast<uintptr_t>(handle) & 1) != 0) {
+    auto it = g_soinfo_handles_map.find(reinterpret_cast<uintptr_t>(handle));
+    if (it == g_soinfo_handles_map.end()) {
+      return nullptr;
+    } else {
+      return it->second;
+    }
+  }
+
+  return static_cast<soinfo*>(handle);
+}
+
 bool do_dlsym(void* handle, const char* sym_name, const char* sym_ver,
               void* caller_addr, void** symbol) {
 #if !defined(__LP64__)
@@ -2430,7 +2416,7 @@
   soinfo* found = nullptr;
   const ElfW(Sym)* sym = nullptr;
   soinfo* caller = find_containing_library(caller_addr);
-  android_namespace_t* ns = caller != nullptr ? caller->get_namespace() : g_anonymous_namespace;
+  android_namespace_t* ns = get_caller_namespace(caller);
 
   version_info vi_instance;
   version_info* vi = nullptr;
@@ -2444,7 +2430,12 @@
   if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) {
     sym = dlsym_linear_lookup(ns, sym_name, vi, &found, caller, handle);
   } else {
-    sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, sym_name, vi);
+    soinfo* si = soinfo_from_handle(handle);
+    if (si == nullptr) {
+      DL_ERR("dlsym failed: invalid handle: %p", handle);
+      return false;
+    }
+    sym = dlsym_handle_lookup(si, &found, sym_name, vi);
   }
 
   if (sym != nullptr) {
@@ -2463,9 +2454,16 @@
   return false;
 }
 
-void do_dlclose(soinfo* si) {
+int do_dlclose(void* handle) {
   ProtectedDataGuard guard;
+  soinfo* si = soinfo_from_handle(handle);
+  if (si == nullptr) {
+    DL_ERR("invalid handle: %p", handle);
+    return -1;
+  }
+
   soinfo_unload(si);
+  return 0;
 }
 
 bool init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_path) {
@@ -2531,7 +2529,7 @@
   soinfo* caller_soinfo = find_containing_library(caller_addr);
 
   android_namespace_t* caller_ns = caller_soinfo != nullptr ?
-                                   caller_soinfo->get_namespace() :
+                                   caller_soinfo->get_primary_namespace() :
                                    g_anonymous_namespace;
 
   ProtectedDataGuard guard;
@@ -2552,12 +2550,10 @@
 
   if ((type & ANDROID_NAMESPACE_TYPE_SHARED) != 0) {
     // If shared - clone the caller namespace
-    auto& soinfo_list = caller_ns->soinfo_list();
-    std::copy(soinfo_list.begin(), soinfo_list.end(), std::back_inserter(ns->soinfo_list()));
+    ns->add_soinfos(caller_ns->soinfo_list());
   } else {
     // If not shared - copy only the global group
-    auto global_group = make_global_group(caller_ns);
-    std::copy(global_group.begin(), global_group.end(), std::back_inserter(ns->soinfo_list()));
+    ns->add_soinfos(make_global_group(caller_ns));
   }
 
   return ns;
@@ -2713,7 +2709,7 @@
     const char* sym_name = nullptr;
     ElfW(Addr) addend = get_addend(rel, reloc);
 
-    DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx);
+    DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx);
     if (type == R_GENERIC_NONE) {
       continue;
     }
@@ -3066,7 +3062,7 @@
     return;
   }
 
-  TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, get_realpath());
+  TRACE("[ Calling %s (size %zd) @ %p for \"%s\" ]", array_name, count, functions, get_realpath());
 
   int begin = reverse ? (count - 1) : 0;
   int end = reverse ? -1 : count;
@@ -3077,7 +3073,7 @@
     call_function("function", functions[i]);
   }
 
-  TRACE("[ Done calling %s for '%s' ]", array_name, get_realpath());
+  TRACE("[ Done calling %s for \"%s\" ]", array_name, get_realpath());
 }
 
 void soinfo::call_function(const char* function_name __unused, linker_function_t function) {
@@ -3085,9 +3081,9 @@
     return;
   }
 
-  TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_realpath());
+  TRACE("[ Calling %s @ %p for \"%s\" ]", function_name, function, get_realpath());
   function();
-  TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_realpath());
+  TRACE("[ Done calling %s @ %p for \"%s\" ]", function_name, function, get_realpath());
 }
 
 void soinfo::call_pre_init_constructors() {
@@ -3172,9 +3168,20 @@
     });
   });
 
-  // 2. Once everything untied - clear local lists.
+  // 2. Remove from the primary namespace
+  primary_namespace_->remove_soinfo(this);
+  primary_namespace_ = nullptr;
+
+  // 3. Remove from secondary namespaces
+  secondary_namespaces_.for_each([&](android_namespace_t* ns) {
+    ns->remove_soinfo(this);
+  });
+
+
+  // 4. Once everything untied - clear local lists.
   parents_.clear();
   children_.clear();
+  secondary_namespaces_.clear();
 }
 
 dev_t soinfo::get_st_dev() const {
@@ -3308,14 +3315,19 @@
   return g_empty_runpath;
 }
 
-android_namespace_t* soinfo::get_namespace() {
+android_namespace_t* soinfo::get_primary_namespace() {
   if (has_min_version(3)) {
-    return namespace_;
+    return primary_namespace_;
   }
 
   return &g_default_namespace;
 }
 
+void soinfo::add_secondary_namespace(android_namespace_t* secondary_ns) {
+  CHECK(has_min_version(3));
+  secondary_namespaces_.push_back(secondary_ns);
+}
+
 ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
   if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
     return call_ifunc_resolver(s->st_value + load_bias);
@@ -3338,7 +3350,7 @@
 }
 
 bool soinfo::can_unload() const {
-  return (get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0;
+  return !is_linked() || ((get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0);
 }
 
 bool soinfo::is_linked() const {
@@ -3349,6 +3361,10 @@
   return (flags_ & FLAG_EXE) != 0;
 }
 
+bool soinfo::is_linker() const {
+  return (flags_ & FLAG_LINKER) != 0;
+}
+
 void soinfo::set_linked() {
   flags_ |= FLAG_LINKED;
 }
@@ -3397,6 +3413,39 @@
   return local_group_root_->target_sdk_version_;
 }
 
+uintptr_t soinfo::get_handle() const {
+  CHECK(has_min_version(3));
+  CHECK(handle_ != 0);
+  return handle_;
+}
+
+void* soinfo::to_handle() {
+  if (get_application_target_sdk_version() <= 23 || !has_min_version(3)) {
+    return this;
+  }
+
+  return reinterpret_cast<void*>(get_handle());
+}
+
+void soinfo::generate_handle() {
+  CHECK(has_min_version(3));
+  CHECK(handle_ == 0); // Make sure this is the first call
+
+  // Make sure the handle is unique and does not collide
+  // with special values which are RTLD_DEFAULT and RTLD_NEXT.
+  do {
+    arc4random_buf(&handle_, sizeof(handle_));
+    // the least significant bit for the handle is always 1
+    // making it easy to test the type of handle passed to
+    // dl* functions.
+    handle_ = handle_ | 1;
+  } while (handle_ == reinterpret_cast<uintptr_t>(RTLD_DEFAULT) ||
+           handle_ == reinterpret_cast<uintptr_t>(RTLD_NEXT) ||
+           g_soinfo_handles_map.find(handle_) != g_soinfo_handles_map.end());
+
+  g_soinfo_handles_map[handle_] = this;
+}
+
 bool soinfo::prelink_image() {
   /* Extract dynamic section */
   ElfW(Word) dynamic_flags = 0;
@@ -3405,7 +3454,7 @@
   /* We can't log anything until the linker is relocated */
   bool relocating_linker = (flags_ & FLAG_LINKER) != 0;
   if (!relocating_linker) {
-    INFO("[ Linking '%s' ]", get_realpath());
+    INFO("[ Linking \"%s\" ]", get_realpath());
     DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
   }
 
@@ -3829,7 +3878,7 @@
     soname_ = basename(realpath_.c_str());
     DL_WARN("%s: is missing DT_SONAME will use basename as a replacement: \"%s\"",
         get_realpath(), soname_);
-    add_dlwarning(get_realpath(), "missing DT_SONAME");
+    // Don't call add_dlwarning because a missing DT_SONAME isn't important enough to show in the UI
   }
   return true;
 }
@@ -3952,10 +4001,9 @@
   }
 #endif
 
-  /* We can also turn on GNU RELRO protection */
-  if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
-    DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
-           get_realpath(), strerror(errno));
+  // We can also turn on GNU RELRO protection if we're not linking the dynamic linker
+  // itself --- it can't make system calls yet, and will have to call protect_relro later.
+  if (!is_linker() && !protect_relro()) {
     return false;
   }
 
@@ -3980,6 +4028,15 @@
   return true;
 }
 
+bool soinfo::protect_relro() {
+  if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
+    DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
+           get_realpath(), strerror(errno));
+    return false;
+  }
+  return true;
+}
+
 /*
  * This function add vdso to internal dso list.
  * It helps to stack unwinding through signal handlers.
@@ -4005,33 +4062,22 @@
 #endif
 }
 
-/*
- * This is linker soinfo for GDB. See details below.
- */
-#if defined(__LP64__)
-#define LINKER_PATH "/system/bin/linker64"
-#else
-#define LINKER_PATH "/system/bin/linker"
-#endif
-
-// This is done to avoid calling c-tor prematurely
-// because soinfo c-tor needs memory allocator
-// which might be initialized after global variables.
-static uint8_t linker_soinfo_for_gdb_buf[sizeof(soinfo)] __attribute__((aligned(8)));
-static soinfo* linker_soinfo_for_gdb = nullptr;
-
 /* gdb expects the linker to be in the debug shared object list.
  * Without this, gdb has trouble locating the linker's ".text"
  * and ".plt" sections. Gdb could also potentially use this to
  * relocate the offset of our exported 'rtld_db_dlactivity' symbol.
- * Don't use soinfo_alloc(), because the linker shouldn't
- * be on the soinfo list.
+ * Note that the linker shouldn't be on the soinfo list.
  */
 static void init_linker_info_for_gdb(ElfW(Addr) linker_base) {
-  linker_soinfo_for_gdb = new (linker_soinfo_for_gdb_buf) soinfo(nullptr, LINKER_PATH,
-                                                                 nullptr, 0, 0);
+  static link_map linker_link_map_for_gdb;
+#if defined(__LP64__)
+  static char kLinkerPath[] = "/system/bin/linker64";
+#else
+  static char kLinkerPath[] = "/system/bin/linker";
+#endif
 
-  linker_soinfo_for_gdb->load_bias = linker_base;
+  linker_link_map_for_gdb.l_addr = linker_base;
+  linker_link_map_for_gdb.l_name = kLinkerPath;
 
   /*
    * Set the dynamic field in the link map otherwise gdb will complain with
@@ -4042,8 +4088,9 @@
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_base);
   ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_base + elf_hdr->e_phoff);
   phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base,
-                                 &linker_soinfo_for_gdb->dynamic, nullptr);
-  insert_soinfo_into_debug_map(linker_soinfo_for_gdb);
+                                 &linker_link_map_for_gdb.l_ld, nullptr);
+
+  insert_link_map_into_debug_map(&linker_link_map_for_gdb);
 }
 
 static void init_default_namespace() {
@@ -4107,31 +4154,29 @@
   if (!getauxval(AT_SECURE)) {
     ldpath_env = getenv("LD_LIBRARY_PATH");
     if (ldpath_env != nullptr) {
-      INFO("[ LD_LIBRARY_PATH set to '%s' ]", ldpath_env);
+      INFO("[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);
     }
     ldpreload_env = getenv("LD_PRELOAD");
     if (ldpreload_env != nullptr) {
-      INFO("[ LD_PRELOAD set to '%s' ]", ldpreload_env);
+      INFO("[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);
     }
   }
 
   soinfo* si = soinfo_alloc(&g_default_namespace, args.argv[0], nullptr, 0, RTLD_GLOBAL);
   if (si == nullptr) {
-    exit(EXIT_FAILURE);
+    __libc_fatal("Couldn't allocate soinfo: out of memory?");
   }
 
   /* bootstrap the link map, the main exe always needs to be first */
   si->set_main_executable();
   link_map* map = &(si->link_map_head);
 
+  // Register the main executable and the linker upfront to have
+  // gdb aware of them before loading the rest of the dependency
+  // tree.
   map->l_addr = 0;
   map->l_name = args.argv[0];
-  map->l_prev = nullptr;
-  map->l_next = nullptr;
-
-  _r_debug.r_map = map;
-  r_debug_tail = map;
-
+  insert_link_map_into_debug_map(map);
   init_linker_info_for_gdb(linker_base);
 
   // Extract information passed from the kernel.
@@ -4157,8 +4202,8 @@
 
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
   if (elf_hdr->e_type != ET_DYN) {
-    __libc_format_fd(2, "error: only position independent executables (PIE) are supported.\n");
-    exit(EXIT_FAILURE);
+    __libc_fatal("\"%s\": error: only position independent executables (PIE) are supported.",
+                 args.argv[0]);
   }
 
   // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
@@ -4170,7 +4215,7 @@
   init_default_namespace();
 
   if (!si->prelink_image()) {
-    __libc_fatal("CANNOT LINK EXECUTABLE: %s", linker_get_error_buffer());
+    __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", args.argv[0], linker_get_error_buffer());
   }
 
   // add somain to global group
@@ -4201,10 +4246,10 @@
       !find_libraries(&g_default_namespace, si, needed_library_names, needed_libraries_count,
                       nullptr, &g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr,
                       /* add_as_children */ true)) {
-    __libc_fatal("CANNOT LINK EXECUTABLE: %s", linker_get_error_buffer());
+    __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", args.argv[0], linker_get_error_buffer());
   } else if (needed_libraries_count == 0) {
     if (!si->link_image(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr)) {
-      __libc_fatal("CANNOT LINK EXECUTABLE: %s", linker_get_error_buffer());
+      __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", args.argv[0], linker_get_error_buffer());
     }
     si->increment_ref_count();
   }
@@ -4266,7 +4311,7 @@
   fflush(stdout);
 #endif
 
-  TRACE("[ Ready to execute '%s' @ %p ]", si->get_realpath(), reinterpret_cast<void*>(si->entry));
+  TRACE("[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(si->entry));
   return si->entry;
 }
 
@@ -4294,8 +4339,9 @@
   return 0;
 }
 
-extern "C" int __set_tls(void*);
-extern "C" void _start();
+static void __linker_cannot_link(KernelArgumentBlock& args) {
+  __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", args.argv[0], linker_get_error_buffer());
+}
 
 /*
  * This is the entry point for the linker, called from begin.S. This
@@ -4309,9 +4355,6 @@
 extern "C" ElfW(Addr) __linker_init(void* raw_args) {
   KernelArgumentBlock args(raw_args);
 
-  void* tls[BIONIC_TLS_SLOTS];
-  __set_tls(tls);
-
   ElfW(Addr) linker_addr = args.getauxval(AT_BASE);
   ElfW(Addr) entry_point = args.getauxval(AT_ENTRY);
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
@@ -4326,7 +4369,10 @@
   // This happens when user tries to run 'adb shell /system/bin/linker'
   // see also https://code.google.com/p/android/issues/detail?id=63174
   if (reinterpret_cast<ElfW(Addr)>(&_start) == entry_point) {
-    __libc_fatal("This is %s, the helper program for shared library executables.", args.argv[0]);
+    __libc_format_fd(STDOUT_FILENO,
+                     "This is %s, the helper program for shared library executables.\n",
+                     args.argv[0]);
+    exit(0);
   }
 
   linker_so.base = linker_addr;
@@ -4337,18 +4383,33 @@
   linker_so.phnum = elf_hdr->e_phnum;
   linker_so.set_linker_flag();
 
+  // Prelink the linker so we can access linker globals.
+  if (!linker_so.prelink_image()) __linker_cannot_link(args);
+
   // This might not be obvious... The reasons why we pass g_empty_list
   // in place of local_group here are (1) we do not really need it, because
   // linker is built with DT_SYMBOLIC and therefore relocates its symbols against
   // itself without having to look into local_group and (2) allocators
   // are not yet initialized, and therefore we cannot use linked_list.push_*
   // functions at this point.
-  if (!(linker_so.prelink_image() && linker_so.link_image(g_empty_list, g_empty_list, nullptr))) {
-    __libc_fatal("CANNOT LINK EXECUTABLE: %s", linker_get_error_buffer());
-  }
+  if (!linker_so.link_image(g_empty_list, g_empty_list, nullptr)) __linker_cannot_link(args);
 
+#if defined(__i386__)
+  // On x86, we can't make system calls before this point.
+  // We can't move this up because this needs to assign to a global.
+  // Note that until we call __libc_init_main_thread below we have
+  // no TLS, so you shouldn't make a system call that can fail, because
+  // it will SEGV when it tries to set errno.
+  __libc_init_sysinfo(args);
+#endif
+
+  // Initialize the main thread (including TLS, so system calls really work).
   __libc_init_main_thread(args);
 
+  // We didn't protect the linker's RELRO pages in link_image because we
+  // couldn't make system calls on x86 at that point, but we can now...
+  if (!linker_so.protect_relro()) __linker_cannot_link(args);
+
   // Initialize the linker's static libc's globals
   __libc_init_globals(args);
 
@@ -4360,7 +4421,7 @@
   // before get_libdl_info().
   solist = get_libdl_info();
   sonext = get_libdl_info();
-  g_default_namespace.soinfo_list().push_back(get_libdl_info());
+  g_default_namespace.add_soinfo(get_libdl_info());
 
   // We have successfully fixed our own relocations. It's safe to run
   // the main part of the linker now.
diff --git a/linker/linker.h b/linker/linker.h
index 389c5b3..a776525 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -114,6 +114,16 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(SoinfoListAllocator);
 };
 
+class NamespaceListAllocator {
+ public:
+  static LinkedListEntry<android_namespace_t>* alloc();
+  static void free(LinkedListEntry<android_namespace_t>* entry);
+
+ private:
+  // unconstructable
+  DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceListAllocator);
+};
+
 class SymbolName {
  public:
   explicit SymbolName(const char* name)
@@ -166,6 +176,7 @@
 struct soinfo {
  public:
   typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
+  typedef LinkedList<android_namespace_t, NamespaceListAllocator> android_namespace_list_t;
 #if defined(__work_around_b_24465209__)
  private:
   char old_name_[SOINFO_NAME_LEN];
@@ -266,6 +277,7 @@
  public:
   soinfo(android_namespace_t* ns, const char* name, const struct stat* file_stat,
          off64_t file_offset, int rtld_flags);
+  ~soinfo();
 
   void call_constructors();
   void call_destructors();
@@ -273,6 +285,7 @@
   bool prelink_image();
   bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
                   const android_dlextinfo* extinfo);
+  bool protect_relro();
 
   void add_child(soinfo* child);
   void remove_all_links();
@@ -310,6 +323,7 @@
   }
 
   bool is_linked() const;
+  bool is_linker() const;
   bool is_main_executable() const;
 
   void set_linked();
@@ -337,11 +351,16 @@
 
   void set_dt_runpath(const char *);
   const std::vector<std::string>& get_dt_runpath() const;
-  android_namespace_t* get_namespace();
+  android_namespace_t* get_primary_namespace();
+  void add_secondary_namespace(android_namespace_t* secondary_ns);
 
   void set_mapped_by_caller(bool reserved_map);
   bool is_mapped_by_caller() const;
 
+  uintptr_t get_handle() const;
+  void generate_handle();
+  void* to_handle();
+
  private:
   bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
   ElfW(Sym)* elf_addr_lookup(const void* addr);
@@ -405,7 +424,9 @@
 
   // version >= 3
   std::vector<std::string> dt_runpath_;
-  android_namespace_t* namespace_;
+  android_namespace_t* primary_namespace_;
+  android_namespace_list_t secondary_namespaces_;
+  uintptr_t handle_;
 
   friend soinfo* get_libdl_info();
 };
@@ -428,8 +449,8 @@
 
 void do_android_get_LD_LIBRARY_PATH(char*, size_t);
 void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
-soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, void* caller_addr);
-void do_dlclose(soinfo* si);
+void* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, void* caller_addr);
+int do_dlclose(void* handle);
 
 int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
 
@@ -440,7 +461,6 @@
 
 void debuggerd_init();
 extern "C" abort_msg_t* g_abort_message;
-extern "C" void notify_gdb_of_libraries();
 
 char* linker_get_error_buffer();
 size_t linker_get_error_buffer_size();
diff --git a/linker/linker_dlwarning.cpp b/linker/linker_dlwarning.cpp
index cd76533..c53ad66 100644
--- a/linker/linker_dlwarning.cpp
+++ b/linker/linker_dlwarning.cpp
@@ -30,9 +30,8 @@
   current_msg = current_msg + basename(sopath) + ": " + message;
 
   if (value != nullptr) {
-    current_msg = current_msg + " \'" + value + "\'";
+    current_msg = current_msg + " \"" + value + "\"";
   }
-
 }
 
 // Resets the current one (like dlerror but instead of
diff --git a/linker/linker_gdb_support.cpp b/linker/linker_gdb_support.cpp
new file mode 100644
index 0000000..de74087
--- /dev/null
+++ b/linker/linker_gdb_support.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "linker_gdb_support.h"
+
+#include <pthread.h>
+
+#include "private/ScopedPthreadMutexLocker.h"
+
+// This function is an empty stub where GDB locates a breakpoint to get notified
+// about linker activity.
+extern "C"
+void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity();
+
+r_debug _r_debug =
+    {1, nullptr, reinterpret_cast<uintptr_t>(&rtld_db_dlactivity), r_debug::RT_CONSISTENT, 0};
+
+static pthread_mutex_t g__r_debug_mutex = PTHREAD_MUTEX_INITIALIZER;
+static link_map* r_debug_tail = nullptr;
+
+void insert_link_map_into_debug_map(link_map* map) {
+  // Stick the new library at the end of the list.
+  // gdb tends to care more about libc than it does
+  // about leaf libraries, and ordering it this way
+  // reduces the back-and-forth over the wire.
+  if (r_debug_tail != nullptr) {
+    r_debug_tail->l_next = map;
+    map->l_prev = r_debug_tail;
+    map->l_next = nullptr;
+  } else {
+    _r_debug.r_map = map;
+    map->l_prev = nullptr;
+    map->l_next = nullptr;
+  }
+  r_debug_tail = map;
+}
+
+void remove_link_map_from_debug_map(link_map* map) {
+  if (r_debug_tail == map) {
+    r_debug_tail = map->l_prev;
+  }
+
+  if (map->l_prev) {
+    map->l_prev->l_next = map->l_next;
+  }
+  if (map->l_next) {
+    map->l_next->l_prev = map->l_prev;
+  }
+}
+
+void notify_gdb_of_load(link_map* map) {
+  ScopedPthreadMutexLocker locker(&g__r_debug_mutex);
+
+  _r_debug.r_state = r_debug::RT_ADD;
+  rtld_db_dlactivity();
+
+  insert_link_map_into_debug_map(map);
+
+  _r_debug.r_state = r_debug::RT_CONSISTENT;
+  rtld_db_dlactivity();
+}
+
+void notify_gdb_of_unload(link_map* map) {
+  ScopedPthreadMutexLocker locker(&g__r_debug_mutex);
+
+  _r_debug.r_state = r_debug::RT_DELETE;
+  rtld_db_dlactivity();
+
+  remove_link_map_from_debug_map(map);
+
+  _r_debug.r_state = r_debug::RT_CONSISTENT;
+  rtld_db_dlactivity();
+}
+
+void notify_gdb_of_libraries() {
+  _r_debug.r_state = r_debug::RT_ADD;
+  rtld_db_dlactivity();
+  _r_debug.r_state = r_debug::RT_CONSISTENT;
+  rtld_db_dlactivity();
+}
+
diff --git a/linker/linker_gdb_support.h b/linker/linker_gdb_support.h
new file mode 100644
index 0000000..2a590ba
--- /dev/null
+++ b/linker/linker_gdb_support.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __LINKER_GDB_SUPPORT_H
+#define __LINKER_GDB_SUPPORT_H
+
+#include <link.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+void insert_link_map_into_debug_map(link_map* map);
+void remove_link_map_from_debug_map(link_map* map);
+void notify_gdb_of_load(link_map* map);
+void notify_gdb_of_unload(link_map* map);
+void notify_gdb_of_libraries();
+
+extern struct r_debug _r_debug;
+
+__END_DECLS
+
+#endif
diff --git a/linker/linker_mips.cpp b/linker/linker_mips.cpp
index 6130066..2d565d7 100644
--- a/linker/linker_mips.cpp
+++ b/linker/linker_mips.cpp
@@ -67,7 +67,7 @@
     ElfW(Addr) sym_addr = 0;
     const char* sym_name = nullptr;
 
-    DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx);
+    DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx);
     if (type == R_GENERIC_NONE) {
       continue;
     }
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index 1b0c4e4..fb070ee 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -20,7 +20,7 @@
 bool normalize_path(const char* path, std::string* normalized_path) {
   // Input should be an absolute path
   if (path[0] != '/') {
-    PRINT("normalize_path - invalid input: '%s', the input path should be absolute", path);
+    PRINT("normalize_path - invalid input: \"%s\", the input path should be absolute", path);
     return false;
   }
 
@@ -89,7 +89,7 @@
   }
 
   const char* const path = normalized_path.c_str();
-  TRACE("Trying zip file open from path '%s' -> normalized '%s'", input_path, path);
+  TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
 
   // Treat an '!/' separator inside a path as the separator between the name
   // of the zip file on disk and the subdirectory to search within it.
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 66d8859..87e5dbc 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -959,6 +959,70 @@
   dlclose(handle2);
 }
 
+TEST(dlext, ns_shared_dlclose) {
+  std::string path = "libc.so:libc++.so:libdl.so:libm.so";
+
+  const std::string lib_path = std::string(getenv("ANDROID_DATA")) + NATIVE_TESTS_PATH;
+
+  android_set_application_target_sdk_version(42U); // something > 23
+
+  ASSERT_TRUE(android_init_namespaces(path.c_str(), nullptr)) << dlerror();
+
+  // preload this library to the default namespace to check if it
+  // is shared later on.
+  void* handle_dlopened =
+          dlopen((lib_path + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
+  ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
+
+  android_namespace_t* ns_isolated_shared =
+          android_create_namespace("private_isolated_shared", nullptr,
+                                   (lib_path + "/private_namespace_libs").c_str(),
+                                   ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
+                                   nullptr);
+  ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
+
+  // Check if "libnstest_dlopened.so" is loaded (and the same)
+  android_dlextinfo extinfo;
+  extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+  extinfo.library_namespace = ns_isolated_shared;
+
+  void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+  ASSERT_TRUE(handle == handle_dlopened);
+  dlclose(handle);
+  dlclose(handle_dlopened);
+
+  // And now check that the library cannot be found by soname (and is no longer loaded)
+  handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
+  ASSERT_TRUE(handle == nullptr)
+      << "Error: libnstest_dlopened.so is still accessible in shared namespace";
+
+  handle = android_dlopen_ext((lib_path + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
+                              RTLD_NOW | RTLD_NOLOAD, &extinfo);
+  ASSERT_TRUE(handle == nullptr)
+      << "Error: libnstest_dlopened.so is still accessible in shared namespace";
+
+  handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
+  ASSERT_TRUE(handle == nullptr)
+      << "Error: libnstest_dlopened.so is still accessible in default namespace";
+
+  handle = dlopen((lib_path + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
+                  RTLD_NOW | RTLD_NOLOAD);
+  ASSERT_TRUE(handle == nullptr)
+      << "Error: libnstest_dlopened.so is still accessible in default namespace";
+
+  // Now lets see if the soinfo area gets reused in the wrong way:
+  // load a library to default namespace.
+  const std::string lib_public_path = lib_path + "/public_namespace_libs/" + g_public_lib;
+  void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
+  ASSERT_TRUE(handle_public != nullptr) << dlerror();
+
+  // try to find it in shared namespace
+  handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
+  ASSERT_TRUE(handle == nullptr)
+      << "Error: " << g_public_lib << " is accessible in shared namespace";
+}
+
 TEST(dlext, ns_anonymous) {
   static const char* root_lib = "libnstest_root.so";
   std::string path = std::string("libc.so:libc++.so:libdl.so:libm.so:") + g_public_lib;
@@ -1050,3 +1114,19 @@
 
   ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
 }
+
+TEST(dlext, dlopen_handle_value_platform) {
+  void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
+  ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
+          << "dlopen should return odd value for the handle";
+  dlclose(handle);
+}
+
+TEST(dlext, dlopen_handle_value_app_compat) {
+  android_set_application_target_sdk_version(23);
+  void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
+  ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
+          << "dlopen should return valid pointer";
+  dlclose(handle);
+}
+
diff --git a/tests/getauxval_test.cpp b/tests/getauxval_test.cpp
index 6ce00f1..63bc963 100644
--- a/tests/getauxval_test.cpp
+++ b/tests/getauxval_test.cpp
@@ -16,6 +16,7 @@
 
 #include <errno.h>
 #include <sys/cdefs.h>
+#include <sys/utsname.h>
 #include <gtest/gtest.h>
 
 // getauxval() was only added as of glibc version 2.16.
@@ -36,28 +37,51 @@
 
 TEST(getauxval, expected_values) {
 #if defined(GETAUXVAL_CAN_COMPILE)
-  ASSERT_EQ((unsigned long int) 0, getauxval(AT_SECURE));
+  ASSERT_EQ(0UL, getauxval(AT_SECURE));
   ASSERT_EQ(getuid(), getauxval(AT_UID));
   ASSERT_EQ(geteuid(), getauxval(AT_EUID));
   ASSERT_EQ(getgid(), getauxval(AT_GID));
   ASSERT_EQ(getegid(), getauxval(AT_EGID));
-  ASSERT_EQ((unsigned long int) getpagesize(), getauxval(AT_PAGESZ));
+  ASSERT_EQ(static_cast<unsigned long>(getpagesize()), getauxval(AT_PAGESZ));
 
-  ASSERT_NE((unsigned long int) 0, getauxval(AT_PHDR));
-  ASSERT_NE((unsigned long int) 0, getauxval(AT_PHNUM));
-  ASSERT_NE((unsigned long int) 0, getauxval(AT_ENTRY));
-  ASSERT_NE((unsigned long int) 0, getauxval(AT_PAGESZ));
+  ASSERT_NE(0UL, getauxval(AT_PHDR));
+  ASSERT_NE(0UL, getauxval(AT_PHNUM));
+  ASSERT_NE(0UL, getauxval(AT_ENTRY));
+  ASSERT_NE(0UL, getauxval(AT_PAGESZ));
 #else
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "This test requires a C library with getauxval.\n";
 #endif
 }
 
 TEST(getauxval, unexpected_values) {
 #if defined(GETAUXVAL_CAN_COMPILE)
   errno = 0;
-  ASSERT_EQ((unsigned long int) 0, getauxval(0xdeadbeef));
+  ASSERT_EQ(0UL, getauxval(0xdeadbeef));
   ASSERT_EQ(ENOENT, errno);
 #else
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "This test requires a C library with getauxval.\n";
 #endif
 }
+
+TEST(getauxval, arm_has_AT_HWCAP2) {
+#if defined(__arm__)
+  // There are no known 32-bit processors that implement any of these instructions, so rather
+  // than require that OEMs backport kernel patches, let's just ignore old hardware. Strictly
+  // speaking this would be fooled by someone choosing to ship a 32-bit kernel on 64-bit hardware,
+  // but that doesn't seem very likely in 2016.
+  utsname u;
+  ASSERT_EQ(0, uname(&u));
+  if (strcmp(u.machine, "aarch64") == 0) {
+    // If this test fails, apps that use getauxval to decide at runtime whether crypto hardware is
+    // available will incorrectly assume that it isn't, and will have really bad performance.
+    // If this test fails, ensure that you've enabled COMPAT_BINFMT_ELF in your kernel configuration.
+    // Note that 0 ("I don't support any of these things") is a legitimate response --- we need
+    // to check errno to see whether we got a "true" 0 or a "not found" 0.
+    errno = 0;
+    getauxval(AT_HWCAP2);
+    ASSERT_EQ(0, errno) << "64-bit kernel not reporting AT_HWCAP2 to 32-bit ARM process";
+    return;
+  }
+#endif
+  GTEST_LOG_(INFO) << "This test is only meaningful for 32-bit ARM code on 64-bit devices.\n";
+}
diff --git a/tests/libs/bionic_tests_zipalign.cpp b/tests/libs/bionic_tests_zipalign.cpp
index dbbfd7c..a72820f 100644
--- a/tests/libs/bionic_tests_zipalign.cpp
+++ b/tests/libs/bionic_tests_zipalign.cpp
@@ -138,6 +138,7 @@
 
   int32_t return_value = OpenArchive(argv[2], &handle);
   if (return_value != 0) {
+    CloseArchive(handle);
     fprintf(stderr, "Unable to open '%s': %s\n", argv[2], ErrorCodeString(return_value));
     return false;
   }
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index d11ea3f..0313171 100755
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -1347,6 +1347,9 @@
 // the wrong map with [stack]. This test verifies that when the above situation happens, the main
 // thread's stack is found correctly.
 TEST(pthread, pthread_attr_getstack_in_signal_handler) {
+  // This test is only meaningful for the main thread, so make sure we're running on it!
+  ASSERT_EQ(getpid(), syscall(__NR_gettid));
+
   const size_t sig_stack_size = 16 * 1024;
   void* sig_stack = mmap(NULL, sig_stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
                          -1, 0);
@@ -1358,6 +1361,12 @@
   stack_t oss;
   ASSERT_EQ(0, sigaltstack(&ss, &oss));
 
+  pthread_attr_t attr;
+  ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attr));
+  void* main_stack_base;
+  size_t main_stack_size;
+  ASSERT_EQ(0, pthread_attr_getstack(&attr, &main_stack_base, &main_stack_size));
+
   ScopedSignalHandler handler(SIGUSR1, getstack_signal_handler, SA_ONSTACK);
   getstack_signal_handler_arg.done = false;
   kill(getpid(), SIGUSR1);
@@ -1369,9 +1378,8 @@
             getstack_signal_handler_arg.signal_handler_sp);
 
   // Verify if the main thread's stack got in the signal handler is correct.
-  ASSERT_LE(getstack_signal_handler_arg.main_stack_base, &ss);
-  ASSERT_GE(reinterpret_cast<char*>(getstack_signal_handler_arg.main_stack_base) +
-            getstack_signal_handler_arg.main_stack_size, reinterpret_cast<void*>(&ss));
+  ASSERT_EQ(main_stack_base, getstack_signal_handler_arg.main_stack_base);
+  ASSERT_LE(main_stack_size, getstack_signal_handler_arg.main_stack_size);
 
   ASSERT_EQ(0, sigaltstack(&oss, nullptr));
   ASSERT_EQ(0, munmap(sig_stack, sig_stack_size));
@@ -1810,55 +1818,82 @@
   ASSERT_EQ(0, pthread_barrierattr_destroy(&attr));
 }
 
-struct BarrierTestHelperArg {
-  std::atomic<pid_t> tid;
-  pthread_barrier_t* barrier;
+struct BarrierTestHelperData {
+  size_t thread_count;
+  pthread_barrier_t barrier;
+  std::atomic<int> finished_mask;
+  std::atomic<int> serial_thread_count;
   size_t iteration_count;
+  std::atomic<size_t> finished_iteration_count;
+
+  BarrierTestHelperData(size_t thread_count, size_t iteration_count)
+      : thread_count(thread_count), finished_mask(0), serial_thread_count(0),
+        iteration_count(iteration_count), finished_iteration_count(0) {
+  }
+};
+
+struct BarrierTestHelperArg {
+  int id;
+  BarrierTestHelperData* data;
 };
 
 static void BarrierTestHelper(BarrierTestHelperArg* arg) {
-  arg->tid = gettid();
-  for (size_t i = 0; i < arg->iteration_count; ++i) {
-    ASSERT_EQ(0, pthread_barrier_wait(arg->barrier));
+  for (size_t i = 0; i < arg->data->iteration_count; ++i) {
+    int result = pthread_barrier_wait(&arg->data->barrier);
+    if (result == PTHREAD_BARRIER_SERIAL_THREAD) {
+      arg->data->serial_thread_count++;
+    } else {
+      ASSERT_EQ(0, result);
+    }
+    arg->data->finished_mask |= (1 << arg->id);
+    if (arg->data->finished_mask == ((1 << arg->data->thread_count) - 1)) {
+      ASSERT_EQ(1, arg->data->serial_thread_count);
+      arg->data->finished_iteration_count++;
+      arg->data->finished_mask = 0;
+      arg->data->serial_thread_count = 0;
+    }
   }
 }
 
 TEST(pthread, pthread_barrier_smoke) {
   const size_t BARRIER_ITERATION_COUNT = 10;
   const size_t BARRIER_THREAD_COUNT = 10;
-  pthread_barrier_t barrier;
-  ASSERT_EQ(0, pthread_barrier_init(&barrier, nullptr, BARRIER_THREAD_COUNT + 1));
-  std::vector<pthread_t> threads(BARRIER_THREAD_COUNT);
+  BarrierTestHelperData data(BARRIER_THREAD_COUNT, BARRIER_ITERATION_COUNT);
+  ASSERT_EQ(0, pthread_barrier_init(&data.barrier, nullptr, data.thread_count));
+  std::vector<pthread_t> threads(data.thread_count);
   std::vector<BarrierTestHelperArg> args(threads.size());
   for (size_t i = 0; i < threads.size(); ++i) {
-    args[i].tid = 0;
-    args[i].barrier = &barrier;
-    args[i].iteration_count = BARRIER_ITERATION_COUNT;
+    args[i].id = i;
+    args[i].data = &data;
     ASSERT_EQ(0, pthread_create(&threads[i], nullptr,
                                 reinterpret_cast<void* (*)(void*)>(BarrierTestHelper), &args[i]));
   }
-  for (size_t iteration = 0; iteration < BARRIER_ITERATION_COUNT; ++iteration) {
-    for (size_t i = 0; i < threads.size(); ++i) {
-      WaitUntilThreadSleep(args[i].tid);
-    }
-    ASSERT_EQ(PTHREAD_BARRIER_SERIAL_THREAD, pthread_barrier_wait(&barrier));
-  }
   for (size_t i = 0; i < threads.size(); ++i) {
     ASSERT_EQ(0, pthread_join(threads[i], nullptr));
   }
-  ASSERT_EQ(0, pthread_barrier_destroy(&barrier));
+  ASSERT_EQ(data.iteration_count, data.finished_iteration_count);
+  ASSERT_EQ(0, pthread_barrier_destroy(&data.barrier));
+}
+
+struct BarrierDestroyTestArg {
+  std::atomic<int> tid;
+  pthread_barrier_t* barrier;
+};
+
+static void BarrierDestroyTestHelper(BarrierDestroyTestArg* arg) {
+  arg->tid = gettid();
+  ASSERT_EQ(0, pthread_barrier_wait(arg->barrier));
 }
 
 TEST(pthread, pthread_barrier_destroy) {
   pthread_barrier_t barrier;
   ASSERT_EQ(0, pthread_barrier_init(&barrier, nullptr, 2));
   pthread_t thread;
-  BarrierTestHelperArg arg;
+  BarrierDestroyTestArg arg;
   arg.tid = 0;
   arg.barrier = &barrier;
-  arg.iteration_count = 1;
   ASSERT_EQ(0, pthread_create(&thread, nullptr,
-                              reinterpret_cast<void* (*)(void*)>(BarrierTestHelper), &arg));
+                              reinterpret_cast<void* (*)(void*)>(BarrierDestroyTestHelper), &arg));
   WaitUntilThreadSleep(arg.tid);
   ASSERT_EQ(EBUSY, pthread_barrier_destroy(&barrier));
   ASSERT_EQ(PTHREAD_BARRIER_SERIAL_THREAD, pthread_barrier_wait(&barrier));
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 8c1e834..c5128ea 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -387,13 +387,15 @@
     "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=66dd34ad31e5963d72a700ec3f2449291d322921\n";
   static siginfo received;
 
-  struct sigaction handler = {};
+  struct sigaction handler;
+  memset(&handler, 0, sizeof(handler));
   handler.sa_sigaction = [](int, siginfo_t* siginfo, void*) { received = *siginfo; };
   handler.sa_flags = SA_SIGINFO;
 
   ASSERT_EQ(0, sigaction(SIGUSR1, &handler, nullptr));
 
-  siginfo sent = {};
+  siginfo sent;
+  memset(&sent, 0, sizeof(sent));
 
   sent.si_code = SI_TKILL;
   ASSERT_EQ(0, syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), SIGUSR1, &sent))
@@ -409,4 +411,14 @@
                                             << sent.si_code << ", received " << received.si_code
                                             << error_msg;
 }
+
+#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
+TEST(signal, sigset_size) {
+  // The setjmp implementations for ARM, AArch64, x86, and x86_64 assume that sigset_t can fit in a
+  // long. This is true because ARM and x86 have broken rt signal support, and AArch64 and x86_64
+  // both have a SIGRTMAX defined as 64.
+  static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long");
+}
+
+#endif
 #endif
diff --git a/tests/stack_protector_test_helper.cpp b/tests/stack_protector_test_helper.cpp
index 34f3c77..53a5e05 100644
--- a/tests/stack_protector_test_helper.cpp
+++ b/tests/stack_protector_test_helper.cpp
@@ -19,6 +19,13 @@
   char buf[128];
   // We can't use memset here because it's fortified, and we want to test
   // the line of defense *after* that.
-  char* p = buf;
-  while ((p - buf) < static_cast<int>(sizeof(buf) + sizeof(void*))) *p++ = '\0';
+  // Without volatile, the generic x86/x86-64 targets don't write to the stack.
+  volatile char* p = buf;
+  int size = static_cast<int>(sizeof(buf) + 1);
+#if __x86_64__
+  // The generic x86-64 target leaves an 8-byte gap between `buf` and the stack guard.
+  // We only need to corrupt one byte though.
+  size += 8;
+#endif
+  while ((p - buf) < size) *p++ = '\0';
 }