Merge jb-dev-mako plus fixes to libc/kernel/common/linux/fb.h

Change-Id: I1fbe64653db7b8e9bfc6e10fa42deb295aa15a09
diff --git a/MAINTAINERS b/MAINTAINERS
deleted file mode 100644
index a76dc24..0000000
--- a/MAINTAINERS
+++ /dev/null
@@ -1,6 +0,0 @@
-
-Bionic support for SuperH
--------------------------
-Bionic support for SuperH architecture is written by
-Shin-ichiro KAWASAKI <shinichiro.kawasaki.mg@hitachi.com>
-and Contributed to Android by Hitachi, Ltd. and Renesas Solutions Corp.
diff --git a/libc/Android.mk b/libc/Android.mk
index 7d31340..4ceb12f 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -140,6 +140,11 @@
 	stdio/vsscanf.c \
 	stdio/wbuf.c \
 	stdio/wsetup.c \
+	stdio/__fgets_chk.c \
+	stdio/__snprintf_chk.c \
+	stdio/__sprintf_chk.c \
+	stdio/__vsnprintf_chk.c \
+	stdio/__vsprintf_chk.c \
 	stdlib/_rand48.c \
 	stdlib/assert.c \
 	stdlib/atexit.c \
@@ -205,6 +210,16 @@
 	string/strtok.c \
 	string/strtotimeval.c \
 	string/strxfrm.c \
+	string/__memcpy_chk.c \
+	string/__memmove_chk.c \
+	string/__memset_chk.c \
+	string/__strcat_chk.c \
+	string/__strcpy_chk.c \
+	string/__strlcat_chk.c \
+	string/__strlcpy_chk.c \
+	string/__strlen_chk.c \
+	string/__strncat_chk.c \
+	string/__strncpy_chk.c \
 	wchar/wcpcpy.c \
 	wchar/wcpncpy.c \
 	wchar/wcscasecmp.c \
@@ -278,7 +293,6 @@
 	bionic/sched_cpucount.c \
 	bionic/semaphore.c \
 	bionic/sha1.c \
-	bionic/ssp.c \
 	bionic/stubs.c \
 	bionic/system_properties.c \
 	bionic/tdelete.c \
@@ -440,18 +454,19 @@
 # Define some common cflags
 # ========================================================
 libc_common_cflags := \
-		-DWITH_ERRLIST			\
-		-DANDROID_CHANGES		\
-		-DUSE_LOCKS 			\
-		-DREALLOC_ZERO_BYTES_FREES 	\
-		-D_LIBC=1 			\
-		-DSOFTFLOAT                     \
-		-DFLOATING_POINT		\
-		-DINET6 \
-		-I$(LOCAL_PATH)/private \
-		-DUSE_DL_PREFIX \
-		-DPOSIX_MISTAKE \
-                -DLOG_ON_HEAP_ERROR \
+    -DWITH_ERRLIST \
+    -DANDROID_CHANGES \
+    -DUSE_LOCKS \
+    -DREALLOC_ZERO_BYTES_FREES \
+    -D_LIBC=1 \
+    -DSOFTFLOAT \
+    -DFLOATING_POINT \
+    -DINET6 \
+    -I$(LOCAL_PATH)/private \
+    -DUSE_DL_PREFIX \
+    -DPOSIX_MISTAKE \
+    -DLOG_ON_HEAP_ERROR \
+    -std=gnu99
 
 # these macro definitions are required to implement the
 # 'timezone' and 'daylight' global variables, as well as
@@ -465,6 +480,13 @@
   libc_common_cflags += -DDEBUG
 endif
 
+# To customize dlmalloc's alignment, set BOARD_MALLOC_ALIGNMENT in
+# the appropriate BoardConfig.mk file.
+#
+ifneq ($(BOARD_MALLOC_ALIGNMENT),)
+  libc_common_cflags += -DMALLOC_ALIGNMENT=$(BOARD_MALLOC_ALIGNMENT)
+endif
+
 ifeq ($(TARGET_ARCH),arm)
   libc_common_cflags += -fstrict-aliasing
   libc_crt_target_cflags := -mthumb-interwork
@@ -478,6 +500,14 @@
   ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
     libc_common_cflags += -DHAVE_ARM_TLS_REGISTER
   endif
+  #
+  # Define HAVE_32_BYTE_CACHE_LINES to indicate to C
+  # library it should use to 32-byte version of memcpy, and not
+  # the 64-byte version.
+  #
+  ifeq ($(ARCH_ARM_HAVE_32_BYTE_CACHE_LINES),true)
+    libc_common_cflags += -DHAVE_32_BYTE_CACHE_LINE
+  endif
   ifeq ($(ARCH_ARM_USE_NON_NEON_MEMCPY),true)
     libc_common_cflags += -DARCH_ARM_USE_NON_NEON_MEMCPY
   endif
@@ -500,8 +530,8 @@
     libc_common_cflags += -DANDROID_SMP=0
 endif
 
-# Needed to access private/__dso_handle.S from
-# crtbegin_xxx.S and crtend_xxx.S
+# Needed to access private/__dso_handle.h from
+# crtbegin_xxx.c and crtend_xxx.c
 #
 libc_crt_target_cflags += -I$(LOCAL_PATH)/private
 
@@ -514,11 +544,11 @@
 libc_common_c_includes := \
 		$(LOCAL_PATH)/stdlib  \
 		$(LOCAL_PATH)/string  \
-		$(LOCAL_PATH)/stdio
+		$(LOCAL_PATH)/stdio   \
+		external/safe-iop/include
 
-# Needed to access private/__dso_handle.S from
+# Needed to access private/__dso_handle.h from
 # crtbegin_xxx.S and crtend_xxx.S
-# and machine/asm.h
 #
 libc_crt_target_cflags += -I$(LOCAL_PATH)/private -I$(LOCAL_PATH)/arch-$(TARGET_ARCH)/include
 
@@ -540,17 +570,21 @@
 #
 
 libc_crt_target_so_cflags := $(libc_crt_target_cflags)
+libc_crt_target_crtstart_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.c
+libc_crt_target_crtstart_so_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.c
 ifeq ($(TARGET_ARCH),x86)
     # This flag must be added for x86 targets, but not for ARM
     libc_crt_target_so_cflags += -fPIC
+    libc_crt_target_crtstart_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.S
+    libc_crt_target_crtstart_so_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.S
 endif
-GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_so.o
-$(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.S
+GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
+$(GEN): $(libc_crt_target_crtstart_so_file)
 	@mkdir -p $(dir $@)
 	$(TARGET_CC) $(libc_crt_target_so_cflags) -o $@ -c $<
 ALL_GENERATED_SOURCES += $(GEN)
 
-GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtend_so.o
+GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
 $(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtend_so.S
 	@mkdir -p $(dir $@)
 	$(TARGET_CC) $(libc_crt_target_so_cflags) -o $@ -c $<
@@ -558,14 +592,14 @@
 endif # TARGET_ARCH == x86 || TARGET_ARCH == arm
 
 
-GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_static.o
-$(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_static.S
+GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
+$(GEN): $(libc_crt_target_crtstart_file)
 	@mkdir -p $(dir $@)
 	$(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
 ALL_GENERATED_SOURCES += $(GEN)
 
-GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_dynamic.o
-$(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_dynamic.S
+GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
+$(GEN): $(libc_crt_target_crtstart_file)
 	@mkdir -p $(dir $@)
 	$(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
 ALL_GENERATED_SOURCES += $(GEN)
@@ -573,7 +607,7 @@
 
 # We rename crtend.o to crtend_android.o to avoid a
 # name clash between gcc and bionic.
-GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtend_android.o
+GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_android.o
 $(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtend.S
 	@mkdir -p $(dir $@)
 	$(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
@@ -585,6 +619,25 @@
 WITH_MALLOC_CHECK_LIBC_A := $(strip $(WITH_MALLOC_CHECK_LIBC_A))
 
 # ========================================================
+# libbionic_ssp.a - stack protector code
+# ========================================================
+#
+# The stack protector code needs to be compiled
+# with -fno-stack-protector, since it modifies the
+# stack canary.
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := bionic/ssp.c
+LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
+LOCAL_C_INCLUDES := $(libc_common_c_includes)
+LOCAL_MODULE := libbionic_ssp
+LOCAL_SYSTEM_SHARED_LIBRARIES :=
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+# ========================================================
 # libc_common.a
 # ========================================================
 include $(CLEAR_VARS)
@@ -596,6 +649,7 @@
 endif
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_common
+LOCAL_WHOLE_STATIC_LIBRARIES := libbionic_ssp
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
 include $(BUILD_STATIC_LIBRARY)
@@ -663,12 +717,6 @@
 # see libc/bionic/pthread_debug.c for details
 
 LOCAL_CFLAGS := $(libc_common_cflags) -DPTHREAD_DEBUG -DPTHREAD_DEBUG_ENABLED=0
-
-ifeq ($(TARGET_ARCH),arm)
-# TODO: At some point, we need to remove this custom linker script.
-LOCAL_LDFLAGS := -Wl,-T,$(BUILD_SYSTEM)/armelf.xsc
-endif
-
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 
 LOCAL_SRC_FILES := \
diff --git a/libc/Jamfile b/libc/Jamfile
deleted file mode 100644
index a65be5d..0000000
--- a/libc/Jamfile
+++ /dev/null
@@ -1,441 +0,0 @@
-# This file is used to build the Bionic library with the Jam build
-# tool. For info, see www.perforce.com/jam/jam.html
-#
-
-BIONIC_TOP ?= $(DOT) ;
-
-DEBUG = 1 ;
-
-# pattern used for automatic heade inclusion detection
-HDRPATTERN = "^[ 	]*#[ 	]*include[ 	]*[<\"]([^\">]*)[\">].*$" ;
-
-
-# debugging support, simply define the DEBUG variable to activate verbose output
-rule Debug
-{
-    if $(DEBUG) {
-        Echo $(1) ;
-    }
-}
-
-# return all elements from $(1) that are not in $(2)
-rule Filter  list : filter
-{
-    local result = ;
-    local item ;
-    for item in $(list) {
-        if ! $(item) in $(filter) {
-            result += $(item) ;
-        }
-    }
-    return $(result) ;
-}
-
-
-# reverse a list of elements
-rule Reverse  list
-{
-    local  result = ;
-    local  item ;
-
-    for item in $(list) {
-        result = $(item) $(result) ;
-    }
-    return $(result) ;
-}
-
-
-# decompose a path into a list of elements
-rule PathDecompose  dir
-{
-    local  result ;
-
-    while $(dir:D)
-    {
-        if ! $(dir:BS) {  # for rooted paths like "/foo"
-            break ;
-        }
-        result = $(dir:BS) $(result) ;
-        dir    = $(dir:D) ;
-    }
-    result = $(dir) $(result) ;
-    return $(result) ;
-}
-
-
-# simply a file path, i.e. get rid of . or .. when possible
-rule _PathSimplify  dir
-{
-    local  result = ;
-    local  dir2 d ;
-
-    dir  = [ PathDecompose $(dir) ] ;
-
-    # get rid of any single dot
-    dir2 = ;
-    for d in $(dir) {
-        if $(d) = "." {
-            continue ;
-        }
-        dir2 += $(d) ;
-    }
-
-    # get rid of .. when possible
-    for d in $(dir2) {
-        if $(d) = ".." && $(result) {
-            result = $(result[2-]) ;
-        }
-        else
-            result = $(d) $(result) ;
-    }
-
-    # now invert the result
-    result = [ Reverse $(result) ] ;
-    if ! $(result) {
-        result = "." ;
-    }
-    return $(result:J="/") ;
-}
-
-
-rule PathSimplify  dirs
-{
-    local result ;
-    local d ;
-    for d in $(dirs) {
-        result += [ _PathSimplify $(d) ] ;
-    }
-    return $(result) ;
-}
-
-
-# retrieve list of subdirectories
-rule ListSubDirs  paths
-{
-    local  result  = ;
-    local  entry ;
-    for entry in [ Glob $(paths) : * ] {
-        if ! $(entry:S) {
-            result += $(entry) ;
-        }
-    }
-    return [ PathSimplify $(result) ] ;
-}
-
-
-# retrieve list of sources in a given directory
-rule ListSources  path
-{
-    return [ Glob $(path) : *.S *.c ] ;
-}
-
-
-# find the prebuilt directory
-#
-if ! $(TOP) {
-    Echo "Please define TOP as the root of your device build tree" ;
-    Exit ;
-}
-
-Debug "OS is" $(OS) ;
-Debug "CPU is" $(CPU) ;
-
-if $(OS) = LINUX
-{
-    PREBUILT = $(TOP)/prebuilt/Linux ;
-}
-else if $(OS) = MACOSX
-{
-    switch $(CPU) {
-        case i386 : PREBUILT = $(TOP)/prebuilt/darwin-x86 ; break ;
-        case ppc  : PREBUILT = $(TOP)/prebuilt/darwin-ppc ; break ;
-        case *    : Echo "unsupported CPU" "$(CPU) !!" ;
-                    Echo "Please contact digit@google.com for help" ;
-                    Exit ;
-    }
-}
-else
-{
-    Echo "Unsupported operating system" $(OS) ;
-    Echo "Please contact digit@google.com for help" ;
-    Exit ;
-}
-
-Debug "TOP is" $(TOP) ;
-Debug "PREBUILT is" $(PREBUILT) ;
-
-
-# check architectures and setup toolchain variables
-#
-SUPPORTED_ARCHS = x86 arm ;
-
-ARCH ?= $(SUPPORTED_ARCHS) ;
-
-if ! $(ARCH) in $(SUPPORTED_ARCHS) {
-    Echo "The variable ARCH contains an unsupported value, use one or more of these instead" ;
-    Echo "separated by spaces:" $(SUPPORTED_ARCHS) ;
-    Exit ;
-}
-
-x86_TOOLSET_PREFIX ?= "" ;
-arm_TOOLSET_PREFIX ?= $(TOP)/prebuilt/Linux/toolchain-4.1.1/bin/arm-elf- ;
-
-for arch in $(ARCH) {
-    CC_$(arch)  = $($(arch)_TOOLSET_PREFIX)gcc ;
-    C++_$(arch) = $($(arch)_TOOLSET_PREFIX)g++ ;
-    AR_$(arch)  = $($(arch)_TOOLSET_PREFIX)ar ;
-}
-
-
-# the list of arch-independent source subdirectories
-BIONIC_SRC_SUBDIRS = string ;
-BIONIC_x86_SUBDIRS = ;
-BIONIC_arm_SUBDIRS = ;
-
-CFLAGS   = -O0 -g -W ;
-
-
-
-# find sources in a given list of subdirectories
-rule FindSources  dirs
-{
-    local dir ;
-
-    for dir in $(dirs)
-    {
-        local LOCAL_SRC NO_LOCAL_SRC ;
-
-        if [ Glob $(dir) : rules.jam ] {
-            include $(dir)/rules.jam ;
-            if $(LOCAL_SRC) {
-                _sources = $(LOCAL_SRC) ;
-            }
-            else {
-                _sources = [ Glob $(dir) : *.S *.c ] ;
-                _sources = $(_sources:BS) ;
-            }
-            if $(NO_LOCAL_SRC) {
-                _sources = [ Filter $(_sources) : $(NO_LOCAL_SRC) ] ;
-            }
-            sources += $(dir)/$(_sources) ;
-        }
-        else
-            sources += [ ListSources $(dir) ] ;
-    }
-}
-
-# Compile a given object file from a source
-rule Compile  object : source
-{
-    Depends $(object) : $(source) ;
-    Depends bionic : $(object) ;
-    Clean clean : $(object) ;
-
-    MakeLocate $(object) : $(OUT) ;
-
-
-    CC on $(object)       = $(CC_$(arch)) ;
-    CFLAGS on $(object)   = $(CFLAGS) ;
-    INCLUDES on $(object) = $(INCLUDES) ;
-    DEFINES on $(object)  = $(DEFINES) ;
-
-    HDRRULE on $(>) = HdrRule ;
-    HDRSCAN on $(>) = $(HDRPATTERN) ;
-    HDRSEARCH on $(>) = $(INCLUDES) ;
-    HDRGRIST on $(>) = $(HDRGRIST) ;
-}
-
-
-actions Compile
-{
-    $(CC) -c -o $(1) $(CFLAGS) -I$(INCLUDES) -D$(DEFINES) $(2)
-}
-
-
-rule RmTemps
-{
-    Temporary $(2) ;
-}
-
-actions quietly updated piecemeal together RmTemps
-{
-    rm -f $(2)
-}
-
-actions Archive
-{
-    $(AR) ru $(1) $(2)
-}
-
-rule Library  library : objects
-{
-    local  obj ;
-
-    if ! $(library:S) {
-        library = $(library:S=.a) ;
-    }
-    library = $(library:G=<$(arch)>) ;
-
-    Depends all : $(library) ;
-
-    if ! $(library:D) {
-        MakeLocate $(library) $(library)($(objects:BS)) : $(OUT) ;
-    }
-
-    Depends $(library) : $(library)($(objects:BS)) ;
-    for obj in $(objects) {
-        Depends $(library)($(obj:BS)) : $(obj) ;
-    }
-
-    Clean clean : $(library) ;
-
-    AR on $(library) = $(AR_$(arch)) ;
-    Archive $(library) : $(objects) ;
-
-    RmTemps $(library) : $(objects) ;
-}
-
-
-rule  ProcessDir
-{
-    local CFLAGS   = $(CFLAGS) ;
-    local DEFINES  = $(DEFINES) ;
-    local INCLUDES = $(INCLUDES) ;
-    local local_rules = [ Glob $(1) : rules.jam ] ;
-    local source sources ;
-
-    if $(local_rules) {
-        local LOCAL_CFLAGS LOCAL_DEFINES LOCAL_INCLUDES LOCAL_SRC NO_LOCAL_SRC ;
-
-        include $(local_rules) ;
-        CFLAGS   += $(LOCAL_CFLAGS) ;
-        DEFINES  += $(LOCAL_DEFINES) ;
-        INCLUDES += $(LOCAL_INCLUDES) ;
-
-        if $(LOCAL_SRC) {
-            sources = $(LOCAL_SRC) ;
-        }
-        else {
-            sources = [ Glob $(1) : *.S *.c ] ;
-            sources = $(sources:BS) ;
-        }
-
-        if $(NO_LOCAL_SRC) {
-            sources = [ Filter $(sources) : $(NO_LOCAL_SRC) ] ;
-        }
-
-        sources = $(1)/$(sources) ;
-    }
-    else
-        sources = [ Glob $(1) : *.S *.c ] ;
-
-    for source in $(sources) {
-        local name = $(source:B) ;
-
-        if $(source:S) = ".S" {
-            # record the list of assembler sources
-            ASSEMBLER_SOURCES += $(name) ;
-        }
-        else if $(source:S) = ".c" && $(name) in $(ASSEMBLER_SOURCES) {
-            # skip C source file if corresponding assembler exists
-            continue ;
-        }
-
-        objname = <$(arch)>$(name).o  ;
-
-        Compile $(objname) : $(source) ;
-        ALL_OBJECTS += $(objname) ;
-    }
-}
-
-rule ProcessDirs
-{
-    local  dir ;
-    for dir in $(1) {
-        ProcessDir $(dir) ;
-    }
-}
-
-INCLUDES_x86 = /usr/src/linux/include ;
-
-INCLUDES_arm = ../kernel_headers
-               include/arch/arm
-               include/bits32
-               ;
-
-INCLUDES = include stdio string stdlib .
-           ../msun/include
-           ;
-
-DEFINES  = ANDROID_CHANGES
-           USE_LOCKS
-           REALLOC_ZERO_BYTES_FREES
-           _LIBC=1
-           SOFTFLOAT
-           FLOATING_POINT
-           NEED_PSELECT=1
-           ANDROID
-           ;
-
-CFLAGS_x86 = ;
-
-
-for arch in $(ARCH)
-{
-    local ARCH_DIR = $(BIONIC_TOP)/arch-$(arch) ;
-    local INCLUDES = $(INCLUDES_$(arch)) $(ARCH_DIR)/include $(INCLUDES) ;
-    local DEFINES  = $(DEFINES_$(arch)) $(DEFINES) ARCH=$(arch)  ;
-    local CFLAGS   = $(CFLAGS) $(CFLAGS_$(arch)) ;
-    local OUT      = out/$(arch) ;
-    local ASSEMBLER_SOURCES ALL_OBJECTS ;
-
-    ProcessDirs [ ListSubDirs $(ARCH_DIR) ] ;
-    ProcessDirs stdlib stdio unistd string tzcode inet ;
-    ProcessDirs [ ListSubDirs netbsd ] ;
-    ProcessDirs bionic ;
-
-    Library bionic : $(ALL_OBJECTS) ;
-}
-
-BIONIC_SEARCH = $(BIONIC_TOP)/include ;
-
-
-
-# /HdrRule source : headers ;
-#
-# Arranges the proper dependencies when the file _source_ includes the files
-# _headers_ through the #include C preprocessor directive
-#
-# this rule is not intendend to be called explicitely. It is called
-# automatically during header scanning on sources handled by the @Object
-# rule (e.g. sources in @Main or @Library rules)
-#
-rule HdrRule
-{
-    # HdrRule source : headers ;
-
-    # N.B.  This rule is called during binding, potentially after
-    # the fate of many targets has been determined, and must be
-    # used with caution: don't add dependencies to unrelated
-    # targets, and don't set variables on $(<).
-
-    # Tell Jam that anything depending on $(<) also depends on $(>),
-    # set SEARCH so Jam can find the headers, but then say we don't
-    # care if we can't actually find the headers (they may have been
-    # within ifdefs),
-
-    local s = $(>:G=$(HDRGRIST:E)) ;
-
-    Includes $(<) : $(s) ;
-    SEARCH on $(s) = $(HDRSEARCH) ;
-    NoCare $(s) ;
-
-    # Propagate on $(<) to $(>)
-
-    HDRSEARCH on $(s) = $(HDRSEARCH) ;
-    HDRSCAN on $(s) = $(HDRSCAN) ;
-    HDRRULE on $(s) = $(HDRRULE) ;
-    HDRGRIST on $(s) = $(HDRGRIST) ;
-}
-
-
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 1923ea0..504a050 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -22,18 +22,18 @@
 #        assembler template for the syscall; it's up to the bionic implementation to provide
 #        a relevant C stub
 #
-#      - additionally, if the syscall number is different amoung ARM, and x86, use:
-#        return_type funcname[:syscall_name](parameters) arm_number,x86_number
+#      - additionally, if the syscall number is different amoung ARM, and x86, MIPS use:
+#        return_type funcname[:syscall_name](parameters) arm_number,x86_number, mips_number
 #
 # the file is processed by a python script named gensyscalls.py
 #
 
 # process management
-void    _exit:exit_group (int)      248,252
+void    _exit:exit_group (int)      248,252,246
 void    _exit_thread:exit (int)     1
 pid_t   __fork:fork (void)           2
-pid_t   _waitpid:waitpid (pid_t, int*, int, struct rusage*)   -1,7
-int     __waitid:waitid(int, pid_t, struct siginfo_t*, int,void*)          280,284
+pid_t   _waitpid:waitpid (pid_t, int*, int, struct rusage*)   -1,7,7
+int     __waitid:waitid(int, pid_t, struct siginfo_t*, int,void*)          280,284,278
 
 # NOTE: this system call is never called directly, but we list it there
 #       to have __NR_clone properly defined.
@@ -42,72 +42,87 @@
 
 int     execve (const char*, char* const*, char* const*)  11
 
-int     __setuid:setuid32 (uid_t)    213
-uid_t   getuid:getuid32 ()         199
-gid_t   getgid:getgid32 ()         200
-uid_t   geteuid:geteuid32 ()       201
-gid_t   getegid:getegid32 ()       202
-uid_t   getresuid:getresuid32 (uid_t *ruid, uid_t *euid, uid_t *suid)   209
-gid_t   getresgid:getresgid32 (gid_t *rgid, gid_t *egid, gid_t *sgid)   211
-pid_t   gettid()                   224
-ssize_t readahead(int, off64_t, size_t)     225
-int     getgroups:getgroups32(int, gid_t *)    205
+int     __setuid:setuid32 (uid_t)    213,213,-1
+int     __setuid:setuid (uid_t)   -1,-1,23
+uid_t   getuid:getuid32 ()         199,199,-1
+uid_t   getuid:getuid ()           -1,-1,24
+gid_t   getgid:getgid32 ()         200,200,-1
+gid_t   getgid:getgid ()           -1,-1,47
+uid_t   geteuid:geteuid32 ()       201,201,-1
+uid_t   geteuid:geteuid ()         -1,-1,49
+gid_t   getegid:getegid32 ()       202,202,-1
+gid_t   getegid:getegid ()         -1,-1,50
+uid_t   getresuid:getresuid32 (uid_t *ruid, uid_t *euid, uid_t *suid)   209,209,-1
+uid_t   getresuid:getresuid (uid_t *ruid, uid_t *euid, uid_t *suid)     -1,-1,186
+gid_t   getresgid:getresgid32 (gid_t *rgid, gid_t *egid, gid_t *sgid)   211,211,-1
+gid_t   getresgid:getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid)     -1,-1,191
+pid_t   gettid()                   224,224,222
+ssize_t readahead(int, off64_t, size_t)     225,225,223
+int     getgroups:getgroups32(int, gid_t *)    205,205,-1
+int     getgroups:getgroups(int, gid_t *)      -1,-1,80
 pid_t   getpgid(pid_t)             132
 pid_t   getppid()                  64
 pid_t   setsid()                   66
-int     setgid:setgid32(gid_t)     214
+int     setgid:setgid32(gid_t)     214,214,-1
+int     setgid:setgid(gid_t)       -1,-1,46
 int     seteuid:seteuid32(uid_t)   stub
-int     __setreuid:setreuid32(uid_t, uid_t)   203
-int     __setresuid:setresuid32(uid_t, uid_t, uid_t)   208
-int     setresgid:setresgid32(gid_t, gid_t, gid_t)   210
+int     __setreuid:setreuid32(uid_t, uid_t)   203,203,-1
+int     __setreuid:setreuid(uid_t, uid_t)     -1,-1,70
+int     __setresuid:setresuid32(uid_t, uid_t, uid_t)   208,208,-1
+int     __setresuid:setresuid(uid_t, uid_t, uid_t)     -1,-1,185
+int     setresgid:setresgid32(gid_t, gid_t, gid_t)   210,210,-1
+int     setresgid:setresgid(gid_t, gid_t, gid_t)     -1,-1,190
 void*   __brk:brk(void*)           45
 # see comments in arch-arm/bionic/kill.S to understand why we don't generate an ARM stub for kill/tkill
-int     kill(pid_t, int)           -1,37
-int     tkill(pid_t tid, int sig)  -1,238
-int     tgkill(pid_t tgid, pid_t tid, int sig)  -1,270
+int     kill(pid_t, int)           -1,37,37
+int     tkill(pid_t tid, int sig)  -1,238,236
+int     tgkill(pid_t tgid, pid_t tid, int sig)  -1,270,266
 int     __ptrace:ptrace(int request, int pid, void* addr, void* data)  26
-int     __set_thread_area:set_thread_area(void*  user_desc)  -1,243
+int     __set_thread_area:set_thread_area(void*  user_desc)  -1,243,283
 int     __getpriority:getpriority(int, int)  96
 int     setpriority(int, int, int)   97
 int     setrlimit(int resource, const struct rlimit *rlp)  75
-int     getrlimit:ugetrlimit(int resource, struct rlimit *rlp)  191
+int     getrlimit:ugetrlimit(int resource, struct rlimit *rlp)  191,191,-1
+int     getrlimit:getrlimit(int resource, struct rlimit *rlp)  -1,-1,76
 int     getrusage(int who, struct rusage*  r_usage)  77
-int     setgroups:setgroups32(int, const gid_t *)   206
+int     setgroups:setgroups32(int, const gid_t *)   206,206,-1
+int     setgroups:setgroups(int, const gid_t *)     -1,-1,81
 pid_t   getpgrp(void)  stub
 int     setpgid(pid_t, pid_t)  57
-pid_t   vfork(void)  190,-1,190
-int     setregid:setregid32(gid_t, gid_t)  204
+pid_t   vfork(void)  190,-1,-1
+int     setregid:setregid32(gid_t, gid_t)  204,204,-1
+int     setregid:setregid(gid_t, gid_t)    -1,-1,71
 int     chroot(const char *)  61
 # IMPORTANT: Even though <sys/prctl.h> declares prctl(int,...), the syscall stub must take 6 arguments
 #            to match the kernel implementation.
-int     prctl(int option, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5)  172
-int     capget(cap_user_header_t header, cap_user_data_t data) 184
-int     capset(cap_user_header_t header, const cap_user_data_t data) 185
-int     sigaltstack(const stack_t*, stack_t*) 186
+int     prctl(int option, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5)  172,172,192
+int     capget(cap_user_header_t header, cap_user_data_t data) 184,184,204
+int     capset(cap_user_header_t header, const cap_user_data_t data) 185,185,205
+int     sigaltstack(const stack_t*, stack_t*) 186,186,206
 int     acct(const char*  filepath)  51
 
 # file descriptors
 ssize_t     read (int, void*, size_t)        3
 ssize_t     write (int, const void*, size_t)       4
-ssize_t     pread64 (int, void *, size_t, off64_t) 180
-ssize_t     pwrite64 (int, void *, size_t, off64_t) 181
+ssize_t     pread64 (int, void *, size_t, off64_t) 180,180,200
+ssize_t     pwrite64 (int, void *, size_t, off64_t) 181,181,201
 int         __open:open (const char*, int, mode_t)  5
-int         __openat:openat (int, const char*, int, mode_t)  322,295
+int         __openat:openat (int, const char*, int, mode_t)  322,295,288
 int         close (int)                      6
 int         creat(const char*, mode_t)       stub
 off_t       lseek(int, off_t, int)           19
 int         __llseek:_llseek (int, unsigned long, unsigned long, loff_t*, int)  140
 pid_t       getpid ()    20
 void *      mmap(void *, size_t, int, int, int, long)  stub
-void *      __mmap2:mmap2(void*, size_t, int, int, int, long)   192
+void *      __mmap2:mmap2(void*, size_t, int, int, int, long)   192,192,210
 int         munmap(void *, size_t)  91
-void *      mremap(void *, size_t, size_t, unsigned long)  163
+void *      mremap(void *, size_t, size_t, unsigned long)  163,163,167
 int         msync(const void *, size_t, int)    144
 int         mprotect(const void *, size_t, int)  125
-int         madvise(const void *, size_t, int)  220,219
-int         mlock(const void *addr, size_t len)    150
-int         munlock(const void *addr, size_t len)   151
-int         mincore(void*  start, size_t  length, unsigned char*  vec)   219,218
+int         madvise(const void *, size_t, int)  220,219,218
+int         mlock(const void *addr, size_t len)    150,150,154
+int         munlock(const void *addr, size_t len)   151,151,155
+int         mincore(void*  start, size_t  length, unsigned char*  vec)   219,218,217
 int         __ioctl:ioctl(int, int, void *)  54
 int         readv(int, const struct iovec *, int)   145
 int         writev(int, const struct iovec *, int)  146
@@ -115,144 +130,147 @@
 int         flock(int, int)   143
 int         fchmod(int, mode_t)  94
 int         dup(int)  41
-int         pipe(int *)  42,42
-int         pipe2(int *, int) 359,331
+int         pipe(int *)  42,42,-1
+int         pipe2(int *, int) 359,331,328
 int         dup2(int, int)   63
 int         select:_newselect(int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *)  142
 int         ftruncate(int, off_t)  93
-int         ftruncate64(int, off64_t) 194
-int         getdents:getdents64(unsigned int, struct dirent *, unsigned int)   217,220
+int         ftruncate64(int, off64_t) 194,194,212
+int         getdents:getdents64(unsigned int, struct dirent *, unsigned int)   217,220,219
 int         fsync(int)  118
-int         fdatasync(int) 148
-int         fchown:fchown32(int, uid_t, gid_t)  207
+int         fdatasync(int) 148,148,152
+int         fchown:fchown32(int, uid_t, gid_t)  207,207,-1
+int         fchown:fchown(int, uid_t, gid_t)    -1,-1,95
 void        sync(void)  36
-int         __fcntl64:fcntl64(int, int, void *)  221
-int         __fstatfs64:fstatfs64(int, size_t, struct statfs *)  267,269
-ssize_t     sendfile(int out_fd, int in_fd, off_t *offset, size_t count)  187
-int         fstatat:fstatat64(int dirfd, const char *path, struct stat *buf, int flags)   327,300
-int         mkdirat(int dirfd, const char *pathname, mode_t mode)  323,296
-int         fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags)  325,298
-int         fchmodat(int dirfd, const char *path, mode_t mode, int flags)  333,306
-int         renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)  329,302
-int         fsetxattr(int, const char *, const void *, size_t, int) 228
-ssize_t     fgetxattr(int, const char *, void *, size_t) 231
-ssize_t     flistxattr(int, char *, size_t) 234
-int         fremovexattr(int, const char *) 237
+int         __fcntl64:fcntl64(int, int, void *)  221,221,220
+int         __fstatfs64:fstatfs64(int, size_t, struct statfs *)  267,269,256
+ssize_t     sendfile(int out_fd, int in_fd, off_t *offset, size_t count)  187,187,207
+int         fstatat:fstatat64(int dirfd, const char *path, struct stat *buf, int flags)   327,300,293
+int         mkdirat(int dirfd, const char *pathname, mode_t mode)  323,296,289
+int         fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags)  325,298,291
+int         fchmodat(int dirfd, const char *path, mode_t mode, int flags)  333,306,299
+int         renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)  329,302,295
+int         fsetxattr(int, const char *, const void *, size_t, int) 228,228,226
+ssize_t     fgetxattr(int, const char *, void *, size_t) 231,231,229
+ssize_t     flistxattr(int, char *, size_t) 234,234,232
+int         fremovexattr(int, const char *) 237,237,235
 
 # file system
 int     link (const char*, const char*)  9
 int     unlink (const char*)             10
-int     unlinkat (int, const char *, int)   328,301
+int     unlinkat (int, const char *, int)   328,301,294
 int     chdir (const char*)              12
 int     mknod (const char*, mode_t, dev_t)  14
 int     chmod (const char*,mode_t)          15
-int     chown:chown32(const char *, uid_t, gid_t)  212
-int     lchown:lchown32 (const char*, uid_t, gid_t)  198
+int     chown:chown32(const char *, uid_t, gid_t)  212,212,-1
+int     chown:chown(const char *, uid_t, gid_t)    -1,-1,202
+int     lchown:lchown32 (const char*, uid_t, gid_t)  198,198,-1
+int     lchown:lchown (const char*, uid_t, gid_t)  -1,-1,16
 int     mount (const char*, const char*, const char*, unsigned long, const void*)  21
 int     umount(const char*)  stub
 int     umount2 (const char*, int)  52
-int     fstat:fstat64(int, struct stat*)    197
-int     stat:stat64(const char *, struct stat *)  195
-int     lstat:lstat64(const char *, struct stat *)  196
+int     fstat:fstat64(int, struct stat*)    197,197,215
+int     stat:stat64(const char *, struct stat *)  195,195,213
+int     lstat:lstat64(const char *, struct stat *)  196,196,214
 int     mkdir(const char *, mode_t) 39
 int     readlink(const char *, char *, size_t)  85
 int     rmdir(const char *)  40
 int     rename(const char *, const char *)  38
-int     __getcwd:getcwd(char * buf, size_t size)  183
+int     __getcwd:getcwd(char * buf, size_t size)  183,183,203
 int     access(const char *, int)  33
-int     faccessat(int, const char *, int, int)  334,307
+int     faccessat(int, const char *, int, int)  334,307,300
 int     symlink(const char *, const char *)  83
 int     fchdir(int)    133
 int     truncate(const char*, off_t)    92
-int     setxattr(const char *, const char *, const void *, size_t, int) 226
-int     lsetxattr(const char *, const char *, const void *, size_t, int) 227
-ssize_t getxattr(const char *, const char *, void *, size_t) 229
-ssize_t lgetxattr(const char *, const char *, void *, size_t) 230
-ssize_t listxattr(const char *, char *, size_t) 232
-ssize_t llistxattr(const char *, char *, size_t) 233
-int     removexattr(const char *, const char *) 235
-int     lremovexattr(const char *, const char *) 236
-int     __statfs64:statfs64(const char *, size_t, struct statfs *)  266,268
+int     setxattr(const char *, const char *, const void *, size_t, int) 226,226,224
+int     lsetxattr(const char *, const char *, const void *, size_t, int) 227,227,225
+ssize_t getxattr(const char *, const char *, void *, size_t) 229,229,227
+ssize_t lgetxattr(const char *, const char *, void *, size_t) 230,230,228
+ssize_t listxattr(const char *, char *, size_t) 232,232,230
+ssize_t llistxattr(const char *, char *, size_t) 233,233,231
+int     removexattr(const char *, const char *) 235,235,233
+int     lremovexattr(const char *, const char *) 236,236,234
+int     __statfs64:statfs64(const char *, size_t, struct statfs *)  266,268,255
 
 # time
 int           pause ()                       29
 int           gettimeofday(struct timeval*, struct timezone*)       78
 int           settimeofday(const struct timeval*, const struct timezone*)   79
 clock_t       times(struct tms *)       43
-int           nanosleep(const struct timespec *, struct timespec *)   162
-int           clock_gettime(clockid_t clk_id, struct timespec *tp)    263,265
-int           clock_settime(clockid_t clk_id, const struct timespec *tp)  262,264
-int           clock_getres(clockid_t clk_id, struct timespec *res)   264,266
-int           clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem)  265,267
+int           nanosleep(const struct timespec *, struct timespec *)   162,162,166
+int           clock_gettime(clockid_t clk_id, struct timespec *tp)    263,265,263
+int           clock_settime(clockid_t clk_id, const struct timespec *tp)  262,264,262
+int           clock_getres(clockid_t clk_id, struct timespec *res)   264,266,264
+int           clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem)  265,267,265
 int           getitimer(int, const struct itimerval *)   105
 int           setitimer(int, const struct itimerval *, struct itimerval *)  104
-int           __timer_create:timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)    257,259
-int           __timer_settime:timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) 258,260
-int           __timer_gettime:timer_gettime(timer_t, struct itimerspec*)                                259,261
-int           __timer_getoverrun:timer_getoverrun(timer_t)                                              260,262
-int           __timer_delete:timer_delete(timer_t)                                                      261,263
-int           utimes(const char*, const struct timeval tvp[2])                          269, 271
-int           utimensat(int, const char *, const struct timespec times[2], int)         348, 320, 320
+int           __timer_create:timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)    257,259,257
+int           __timer_settime:timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) 258,260,258
+int           __timer_gettime:timer_gettime(timer_t, struct itimerspec*)                                259,261,259
+int           __timer_getoverrun:timer_getoverrun(timer_t)                                              260,262,260
+int           __timer_delete:timer_delete(timer_t)                                                      261,263,261
+int           utimes(const char*, const struct timeval tvp[2])                          269,271,267
+int           utimensat(int, const char *, const struct timespec times[2], int)         348,320,316
 
 # signals
 int     sigaction(int, const struct sigaction *, struct sigaction *)  67
 int     sigprocmask(int, const sigset_t *, sigset_t *)  126
 int     __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask)  72
-int     __rt_sigaction:rt_sigaction (int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize)  174
-int     __rt_sigprocmask:rt_sigprocmask (int  how, const sigset_t *set, sigset_t *oset, size_t sigsetsize)  175
-int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t  *info, struct timespec_t  *timeout, size_t  sigset_size)  177
+int     __rt_sigaction:rt_sigaction (int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize)  174,174,194
+int     __rt_sigprocmask:rt_sigprocmask (int  how, const sigset_t *set, sigset_t *oset, size_t sigsetsize)  175,175,195
+int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t  *info, struct timespec_t  *timeout, size_t  sigset_size)  177,177,197
 int     sigpending(sigset_t *)  73
 
 # sockets
-int           socket(int, int, int)              281,-1
-int           socketpair(int, int, int, int*)    288,-1
-int           bind(int, struct sockaddr *, int)  282,-1
-int           connect(int, struct sockaddr *, socklen_t)   283,-1
-int           listen(int, int)                   284,-1
-int           accept(int, struct sockaddr *, socklen_t *)  285,-1
-int           getsockname(int, struct sockaddr *, socklen_t *)  286,-1
-int           getpeername(int, struct sockaddr *, socklen_t *)  287,-1
-int           sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  290,-1
-int           recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  292,-1
-int           shutdown(int, int)  293,-1
-int           setsockopt(int, int, int, const void *, socklen_t)  294,-1
-int           getsockopt(int, int, int, void *, socklen_t *)    295,-1
-int           sendmsg(int, const struct msghdr *, unsigned int)  296,-1
-int           recvmsg(int, struct msghdr *, unsigned int)   297,-1
+int           socket(int, int, int)              281,-1,183
+int           socketpair(int, int, int, int*)    288,-1,184
+int           bind(int, struct sockaddr *, int)  282,-1,169
+int           connect(int, struct sockaddr *, socklen_t)   283,-1,170
+int           listen(int, int)                   284,-1,174
+int           accept(int, struct sockaddr *, socklen_t *)  285,-1,168
+int           getsockname(int, struct sockaddr *, socklen_t *)  286,-1,172
+int           getpeername(int, struct sockaddr *, socklen_t *)  287,-1,171
+int           sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  290,-1,180
+int           recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  292,-1,176
+int           shutdown(int, int)  293,-1,182
+int           setsockopt(int, int, int, const void *, socklen_t)  294,-1,181
+int           getsockopt(int, int, int, void *, socklen_t *)    295,-1,173
+int           sendmsg(int, const struct msghdr *, unsigned int)  296,-1,179
+int           recvmsg(int, struct msghdr *, unsigned int)   297,-1,177
 
 # sockets for x86. These are done as an "indexed" call to socketcall syscall.
-int           socket:socketcall:1 (int, int, int) -1,102
-int           bind:socketcall:2 (int, struct sockaddr *, int)  -1,102
-int           connect:socketcall:3(int, struct sockaddr *, socklen_t)   -1,102
-int           listen:socketcall:4(int, int)                   -1,102
-int           accept:socketcall:5(int, struct sockaddr *, socklen_t *)  -1,102
-int           getsockname:socketcall:6(int, struct sockaddr *, socklen_t *)  -1,102
-int           getpeername:socketcall:7(int, struct sockaddr *, socklen_t *)  -1,102
-int           socketpair:socketcall:8(int, int, int, int*)    -1,102
-int           sendto:socketcall:11(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  -1,102
-int           recvfrom:socketcall:12(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  -1,102
+int           socket:socketcall:1 (int, int, int) -1,102,-1
+int           bind:socketcall:2 (int, struct sockaddr *, int)  -1,102,-1
+int           connect:socketcall:3(int, struct sockaddr *, socklen_t)   -1,102,-1
+int           listen:socketcall:4(int, int)                   -1,102,-1
+int           accept:socketcall:5(int, struct sockaddr *, socklen_t *)  -1,102,-1
+int           getsockname:socketcall:6(int, struct sockaddr *, socklen_t *)  -1,102,-1
+int           getpeername:socketcall:7(int, struct sockaddr *, socklen_t *)  -1,102,-1
+int           socketpair:socketcall:8(int, int, int, int*)    -1,102,-1
+int           sendto:socketcall:11(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  -1,102,-1
+int           recvfrom:socketcall:12(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  -1,102,-1
 int           shutdown:socketcall:13(int, int)  -1,102,-1
-int           setsockopt:socketcall:14(int, int, int, const void *, socklen_t)  -1,102
-int           getsockopt:socketcall:15(int, int, int, void *, socklen_t *)    -1,102
-int           sendmsg:socketcall:16(int, const struct msghdr *, unsigned int)  -1,102
-int           recvmsg:socketcall:17(int, struct msghdr *, unsigned int)   -1,102
+int           setsockopt:socketcall:14(int, int, int, const void *, socklen_t)  -1,102,-1
+int           getsockopt:socketcall:15(int, int, int, void *, socklen_t *)    -1,102,-1
+int           sendmsg:socketcall:16(int, const struct msghdr *, unsigned int)  -1,102,-1
+int           recvmsg:socketcall:17(int, struct msghdr *, unsigned int)   -1,102,-1
 
 # scheduler & real-time
-int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param)  156
-int sched_getscheduler(pid_t pid)  157
-int sched_yield(void)  158
-int sched_setparam(pid_t pid, const struct sched_param *param)  154
-int sched_getparam(pid_t pid, struct sched_param *param)  155
-int sched_get_priority_max(int policy)  159
-int sched_get_priority_min(int policy)  160
-int sched_rr_get_interval(pid_t pid, struct timespec *interval)  161
-int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 241
-int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)  242
-int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 345,318
+int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param)  156,156,160
+int sched_getscheduler(pid_t pid)  157,157,161
+int sched_yield(void)  158,158,162
+int sched_setparam(pid_t pid, const struct sched_param *param)  154,154,158
+int sched_getparam(pid_t pid, struct sched_param *param)  155,155,159
+int sched_get_priority_max(int policy)  159,159,163
+int sched_get_priority_min(int policy)  160,160,164
+int sched_rr_get_interval(pid_t pid, struct timespec *interval)  161,161,165
+int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 241,241,239
+int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)  242,242,240
+int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 345,318,312
 
 # io priorities
-int ioprio_set(int which, int who, int ioprio) 314,289
-int ioprio_get(int which, int who) 315,290
+int ioprio_set(int which, int who, int ioprio) 314,289,314
+int ioprio_get(int which, int who) 315,290,315
 
 # other
 int     uname(struct utsname *)  122
@@ -268,21 +286,25 @@
 long    perf_event_open(struct perf_event_attr *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags) 364
 
 # futex
-int	futex(void *, int, int, void *, void *, int) 240
+int	futex(void *, int, int, void *, void *, int) 240,240,238
 
 # epoll
-int     epoll_create(int size)     250,254
-int     epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)    251,255
-int     epoll_wait(int epfd, struct epoll_event *events, int max, int timeout)   252,256
+int     epoll_create(int size)     250,254,248
+int     epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)    251,255,249
+int     epoll_wait(int epfd, struct epoll_event *events, int max, int timeout)   252,256,250
 
-int     inotify_init(void)      316,291,290
-int     inotify_add_watch(int, const char *, unsigned int)  317,292
-int     inotify_rm_watch(int, unsigned int)  318,293
+int     inotify_init(void)      316,291,284
+int     inotify_add_watch(int, const char *, unsigned int)  317,292,285
+int     inotify_rm_watch(int, unsigned int)  318,293,286
 
-int     poll(struct pollfd *, unsigned int, long)  168
+int     poll(struct pollfd *, unsigned int, long)  168,168,188
 
-int     eventfd:eventfd2(unsigned int, int)  356,328
+int     eventfd:eventfd2(unsigned int, int)  356,328,325
 
 # ARM-specific ARM_NR_BASE == 0x0f0000 == 983040
-int     __set_tls:ARM_set_tls(void*)                                 983045,-1
-int     cacheflush:ARM_cacheflush(long start, long end, long flags)  983042,-1
+int     __set_tls:ARM_set_tls(void*)                                 983045,-1,-1
+int     cacheflush:ARM_cacheflush(long start, long end, long flags)  983042,-1,-1
+
+# MIPS-specific
+int	_flush_cache:cacheflush(char *addr, const int nbytes, const int op)	-1,-1,147
+int	syscall(int number,...) -1,-1,0
diff --git a/libc/arch-arm/bionic/atexit.S b/libc/arch-arm/bionic/atexit.h
similarity index 61%
rename from libc/arch-arm/bionic/atexit.S
rename to libc/arch-arm/bionic/atexit.h
index beea685..d567bfc 100644
--- a/libc/arch-arm/bionic/atexit.S
+++ b/libc/arch-arm/bionic/atexit.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,37 +26,28 @@
  * SUCH DAMAGE.
  */
 
+/* CRT_LEGACY_WORKAROUND should only be defined when building
+ * this file as part of the platform's C library.
+ *
+ * The C library already defines a function named 'atexit()'
+ * for backwards compatibility with older NDK-generated binaries.
+ *
+ * For newer ones, 'atexit' is actually embedded in the C
+ * runtime objects that are linked into the final ELF
+ * binary (shared library or executable), and will call
+ * __cxa_atexit() in order to un-register any atexit()
+ * handler when a library is unloaded.
+ *
+ * This function must be global *and* hidden. Only the
+ * code inside the same ELF binary should be able to access it.
+ */
+
 #ifndef CRT_LEGACY_WORKAROUND
-	.arch armv5te
-	.fpu softvfp
-	.eabi_attribute 20, 1
-	.eabi_attribute 21, 1
-	.eabi_attribute 23, 3
-	.eabi_attribute 24, 1
-	.eabi_attribute 25, 1
-	.eabi_attribute 26, 2
-	.eabi_attribute 30, 4
-	.eabi_attribute 18, 4
-	.hidden	atexit
-	.code	16
-	.thumb_func
-ENTRY(atexit)
-.LFB0:
-	.save	{r4, lr}
-	push	{r4, lr}
-.LCFI0:
-	ldr	r3, .L3
-	mov	r1, #0
-	@ sp needed for prologue
-.LPIC0:
-	add	r3, pc
-	ldr	r2, [r3]
-	bl	__cxa_atexit
-	pop	{r4, pc}
-.L4:
-	.align	2
-.L3:
-	.word	__dso_handle-(.LPIC0+4)
-.LFE0:
-END(atexit)
+extern void *__dso_handle;
+
+__attribute__ ((visibility ("hidden")))
+int atexit(void (*func)(void))
+{
+  return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle));
+}
 #endif
diff --git a/libc/arch-arm/bionic/crtbegin.c b/libc/arch-arm/bionic/crtbegin.c
new file mode 100644
index 0000000..9dcd254
--- /dev/null
+++ b/libc/arch-arm/bionic/crtbegin.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+typedef struct
+{
+    void (**preinit_array)(void);
+    void (**init_array)(void);
+    void (**fini_array)(void);
+    void (**ctors_array)(void);
+} structors_array_t;
+
+extern int main(int argc, char **argv, char **env);
+
+extern void __libc_init(
+  unsigned int *elfdata,
+  void (*onexit)(void),
+  int (*slingshot)(int, char**, char**),
+  structors_array_t const * const structors
+);
+
+__attribute__ ((section (".preinit_array")))
+void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1;
+
+__attribute__ ((section (".init_array")))
+void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
+
+__attribute__ ((section (".fini_array")))
+void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
+
+__attribute__ ((section (".ctors")))
+void (*__CTOR_LIST__)(void) = (void (*)(void)) -1;
+
+__attribute__((visbility("hidden")))
+void _start() {
+  structors_array_t array;
+  void *elfdata;
+
+  array.preinit_array = &__PREINIT_ARRAY__;
+  array.init_array =    &__INIT_ARRAY__;
+  array.fini_array =    &__FINI_ARRAY__;
+  array.ctors_array =   &__CTOR_LIST__;
+
+  elfdata = __builtin_frame_address(0) + sizeof(void *);
+  __libc_init(elfdata, (void *) 0, &main, &array);
+}
+
+#include "__dso_handle.h"
+#include "atexit.h"
diff --git a/libc/arch-arm/bionic/crtbegin_dynamic.S b/libc/arch-arm/bionic/crtbegin_dynamic.S
deleted file mode 100644
index ec6d482..0000000
--- a/libc/arch-arm/bionic/crtbegin_dynamic.S
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-	.text
-	.align 4
-	.type _start,#function
-	.globl _start
-
-# this is the small startup code that is first run when
-# any executable that is dynamically-linked with Bionic
-# runs.
-#
-# it's purpose is to call __libc_init with appropriate
-# arguments, which are:
-#
-#    - the address of the raw data block setup by the Linux
-#      kernel ELF loader
-#
-#    - address of an "onexit" function, not used on any
-#      platform supported by Bionic
-#
-#    - address of the "main" function of the program.
-#
-#    - address of the constructor list
-#
-_start:	
-	mov	r0, sp
-	mov	r1, #0
-	ldr	r2, =main
-	adr	r3, 1f
-	ldr	r4, =__libc_init
-	blx	r4
-	mov	r0, #0
-	bx	r0
-
-1:  .long   __PREINIT_ARRAY__
-    .long   __INIT_ARRAY__
-    .long   __FINI_ARRAY__
-    .long   __CTOR_LIST__
-
-	.section .preinit_array, "aw"
-	.globl __PREINIT_ARRAY__
-__PREINIT_ARRAY__:
-	.long -1
-
-	.section .init_array, "aw"
-	.globl __INIT_ARRAY__
-__INIT_ARRAY__:
-	.long -1
-
-	.section .fini_array, "aw"
-	.globl __FINI_ARRAY__
-__FINI_ARRAY__:
-	.long -1
-
-	.section .ctors, "aw"
-	.globl __CTOR_LIST__
-__CTOR_LIST__:
-	.long -1
-
-#include "__dso_handle.S"
-#include "atexit.S"
diff --git a/libc/arch-arm/bionic/crtbegin_so.S b/libc/arch-arm/bionic/crtbegin_so.S
deleted file mode 100644
index 104d214..0000000
--- a/libc/arch-arm/bionic/crtbegin_so.S
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <machine/asm.h>
-
-# Implement static C++ destructors when the shared
-# library is unloaded through dlclose().
-#
-# A call to this function must be the first entry
-# in the .fini_array. See 3.3.5.3.C of C++ ABI
-# standard.
-#
-ENTRY(__on_dlclose)
-        adr     r0, 0f
-        ldr     r0, [r0]
-        b       __cxa_finalize
-END(__on_dlclose)
-
-0:
-        .long   __dso_handle
-
-	.section .init_array, "aw"
-	.globl __INIT_ARRAY__
-__INIT_ARRAY__:
-	.long -1
-
-        .section .fini_array, "aw"
-        .globl __FINI_ARRAY__
-__FINI_ARRAY__:
-        .long -1
-        .long __on_dlclose
-
-#ifdef CRT_LEGACY_WORKAROUND
-#include "__dso_handle.S"
-#else
-#include "__dso_handle_so.S"
-#endif
-
-#include "atexit.S"
diff --git a/libdl/arch-sh/soend.S b/libc/arch-arm/bionic/crtbegin_so.c
similarity index 79%
copy from libdl/arch-sh/soend.S
copy to libc/arch-arm/bionic/crtbegin_so.c
index 7fa98a4..57d19bf 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/arch-arm/bionic/crtbegin_so.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,18 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+extern void __cxa_finalize(void *);
+extern void *__dso_handle;
 
+__attribute__((visbility("hidden")))
+void __on_dlclose() {
+  __cxa_finalize(&__dso_handle);
+}
+
+#ifdef CRT_LEGACY_WORKAROUND
+#include "__dso_handle.h"
+#else
+#include "__dso_handle_so.h"
+#endif
+
+#include "atexit.h"
diff --git a/libc/arch-arm/bionic/crtbegin_static.S b/libc/arch-arm/bionic/crtbegin_static.S
deleted file mode 100644
index 087ce36..0000000
--- a/libc/arch-arm/bionic/crtbegin_static.S
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-	.text
-	.align 4
-	.type _start,#function
-	.globl _start
-
-# this is the small startup code that is first run when
-# any executable that is statically-linked with Bionic
-# runs.
-#
-# it's purpose is to call __libc_init with appropriate
-# arguments, which are:
-#
-#    - the address of the raw data block setup by the Linux
-#      kernel ELF loader
-#
-#    - address of an "onexit" function, not used on any
-#      platform supported by Bionic
-#
-#    - address of the "main" function of the program.
-#
-#    - address of the constructor list
-#
-_start:	
-	mov	r0, sp
-	mov	r1, #0
-	ldr	r2, =main
-	adr	r3, 1f
-	ldr	r4, =__libc_init
-	blx	r4
-	mov	r0, #0
-	bx	r0
-
-1:  .long   __PREINIT_ARRAY__
-    .long   __INIT_ARRAY__
-    .long   __FINI_ARRAY__
-    .long   __CTOR_LIST__
-
-	.section .preinit_array, "aw"
-	.globl __PREINIT_ARRAY__
-__PREINIT_ARRAY__:
-	.long -1
-
-	.section .init_array, "aw"
-	.globl __INIT_ARRAY__
-__INIT_ARRAY__:
-	.long -1
-
-	.section .fini_array, "aw"
-	.globl __FINI_ARRAY__
-__FINI_ARRAY__:
-	.long -1
-
-	.section .ctors, "aw"
-	.globl __CTOR_LIST__
-__CTOR_LIST__:
-	.long -1
-
-
-#include "__dso_handle.S"
-#include "atexit.S"
diff --git a/libc/arch-arm/bionic/memcpy.S b/libc/arch-arm/bionic/memcpy.S
index 8c0b4d7..8453cc0 100644
--- a/libc/arch-arm/bionic/memcpy.S
+++ b/libc/arch-arm/bionic/memcpy.S
@@ -34,23 +34,28 @@
         .text
         .fpu    neon
 
+#ifdef HAVE_32_BYTE_CACHE_LINE
+/* a prefetch distance of 2 cache-lines */
+#define CACHE_LINE_SIZE     32
+#define PREFETCH_DISTANCE   (CACHE_LINE_SIZE*2)
+#else
 /* a prefetch distance of 4 cache-lines works best experimentally */
 #define CACHE_LINE_SIZE     64
 #define PREFETCH_DISTANCE   (CACHE_LINE_SIZE*4)
+#endif
 
 ENTRY(memcpy)
         .save       {r0, lr}
-        stmfd       sp!, {r0, lr}
-
         /* start preloading as early as possible */
         pld         [r1, #(CACHE_LINE_SIZE*0)]
+        stmfd       sp!, {r0, lr}
         pld         [r1, #(CACHE_LINE_SIZE*1)]
 
         /* do we have at least 16-bytes to copy (needed for alignment below) */
         cmp         r2, #16
         blo         5f
 
-        /* align destination to half cache-line for the write-buffer */
+        /* align destination to cache-line for the write-buffer */
         rsb         r3, r0, #0
         ands        r3, r3, #0xF
         beq         0f
@@ -79,6 +84,26 @@
         pld         [r1, #(CACHE_LINE_SIZE*0)]
         pld         [r1, #(CACHE_LINE_SIZE*1)]
 
+#ifdef HAVE_32_BYTE_CACHE_LINE
+        /* make sure we have at least 32 bytes to copy */
+        subs        r2, r2, #32
+        blo         4f
+
+        /* preload all the cache lines we need.
+         * NOTE: the number of pld below depends on PREFETCH_DISTANCE,
+         * ideally would would increase the distance in the main loop to
+         * avoid the goofy code below. In practice this doesn't seem to make
+         * a big difference.
+         */
+        pld         [r1, #(PREFETCH_DISTANCE)]
+
+1:      /* The main loop copies 32 bytes at a time */
+        vld1.8      {d0  - d3},   [r1]!
+        pld         [r1, #(PREFETCH_DISTANCE)]
+        subs        r2, r2, #32
+        vst1.8      {d0  - d3},   [r0, :128]!
+        bhs         1b
+#else
         /* make sure we have at least 64 bytes to copy */
         subs        r2, r2, #64
         blo         2f
@@ -112,7 +137,7 @@
         subs        r2, r2, #32
         vst1.8      {d0 - d3},  [r0, :128]!
         bhs         3b
-
+#endif
 4:      /* less than 32 left */
         add         r2, r2, #32
         tst         r2, #0x10
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
new file mode 100644
index 0000000..8c0c4dc
--- /dev/null
+++ b/libc/arch-mips/syscalls.mk
@@ -0,0 +1,201 @@
+# auto-generated by gensyscalls.py, do not touch
+syscall_src := 
+syscall_src += arch-mips/syscalls/_exit.S
+syscall_src += arch-mips/syscalls/_exit_thread.S
+syscall_src += arch-mips/syscalls/__fork.S
+syscall_src += arch-mips/syscalls/_waitpid.S
+syscall_src += arch-mips/syscalls/__waitid.S
+syscall_src += arch-mips/syscalls/__sys_clone.S
+syscall_src += arch-mips/syscalls/execve.S
+syscall_src += arch-mips/syscalls/__setuid.S
+syscall_src += arch-mips/syscalls/getuid.S
+syscall_src += arch-mips/syscalls/getgid.S
+syscall_src += arch-mips/syscalls/geteuid.S
+syscall_src += arch-mips/syscalls/getegid.S
+syscall_src += arch-mips/syscalls/getresuid.S
+syscall_src += arch-mips/syscalls/getresgid.S
+syscall_src += arch-mips/syscalls/gettid.S
+syscall_src += arch-mips/syscalls/readahead.S
+syscall_src += arch-mips/syscalls/getgroups.S
+syscall_src += arch-mips/syscalls/getpgid.S
+syscall_src += arch-mips/syscalls/getppid.S
+syscall_src += arch-mips/syscalls/setsid.S
+syscall_src += arch-mips/syscalls/setgid.S
+syscall_src += arch-mips/syscalls/__setreuid.S
+syscall_src += arch-mips/syscalls/__setresuid.S
+syscall_src += arch-mips/syscalls/setresgid.S
+syscall_src += arch-mips/syscalls/__brk.S
+syscall_src += arch-mips/syscalls/kill.S
+syscall_src += arch-mips/syscalls/tkill.S
+syscall_src += arch-mips/syscalls/tgkill.S
+syscall_src += arch-mips/syscalls/__ptrace.S
+syscall_src += arch-mips/syscalls/__set_thread_area.S
+syscall_src += arch-mips/syscalls/__getpriority.S
+syscall_src += arch-mips/syscalls/setpriority.S
+syscall_src += arch-mips/syscalls/setrlimit.S
+syscall_src += arch-mips/syscalls/getrlimit.S
+syscall_src += arch-mips/syscalls/getrusage.S
+syscall_src += arch-mips/syscalls/setgroups.S
+syscall_src += arch-mips/syscalls/setpgid.S
+syscall_src += arch-mips/syscalls/setregid.S
+syscall_src += arch-mips/syscalls/chroot.S
+syscall_src += arch-mips/syscalls/prctl.S
+syscall_src += arch-mips/syscalls/capget.S
+syscall_src += arch-mips/syscalls/capset.S
+syscall_src += arch-mips/syscalls/sigaltstack.S
+syscall_src += arch-mips/syscalls/acct.S
+syscall_src += arch-mips/syscalls/read.S
+syscall_src += arch-mips/syscalls/write.S
+syscall_src += arch-mips/syscalls/pread64.S
+syscall_src += arch-mips/syscalls/pwrite64.S
+syscall_src += arch-mips/syscalls/__open.S
+syscall_src += arch-mips/syscalls/__openat.S
+syscall_src += arch-mips/syscalls/close.S
+syscall_src += arch-mips/syscalls/lseek.S
+syscall_src += arch-mips/syscalls/__llseek.S
+syscall_src += arch-mips/syscalls/getpid.S
+syscall_src += arch-mips/syscalls/__mmap2.S
+syscall_src += arch-mips/syscalls/munmap.S
+syscall_src += arch-mips/syscalls/mremap.S
+syscall_src += arch-mips/syscalls/msync.S
+syscall_src += arch-mips/syscalls/mprotect.S
+syscall_src += arch-mips/syscalls/madvise.S
+syscall_src += arch-mips/syscalls/mlock.S
+syscall_src += arch-mips/syscalls/munlock.S
+syscall_src += arch-mips/syscalls/mincore.S
+syscall_src += arch-mips/syscalls/__ioctl.S
+syscall_src += arch-mips/syscalls/readv.S
+syscall_src += arch-mips/syscalls/writev.S
+syscall_src += arch-mips/syscalls/__fcntl.S
+syscall_src += arch-mips/syscalls/flock.S
+syscall_src += arch-mips/syscalls/fchmod.S
+syscall_src += arch-mips/syscalls/dup.S
+syscall_src += arch-mips/syscalls/pipe2.S
+syscall_src += arch-mips/syscalls/dup2.S
+syscall_src += arch-mips/syscalls/select.S
+syscall_src += arch-mips/syscalls/ftruncate.S
+syscall_src += arch-mips/syscalls/ftruncate64.S
+syscall_src += arch-mips/syscalls/getdents.S
+syscall_src += arch-mips/syscalls/fsync.S
+syscall_src += arch-mips/syscalls/fdatasync.S
+syscall_src += arch-mips/syscalls/fchown.S
+syscall_src += arch-mips/syscalls/sync.S
+syscall_src += arch-mips/syscalls/__fcntl64.S
+syscall_src += arch-mips/syscalls/__fstatfs64.S
+syscall_src += arch-mips/syscalls/sendfile.S
+syscall_src += arch-mips/syscalls/fstatat.S
+syscall_src += arch-mips/syscalls/mkdirat.S
+syscall_src += arch-mips/syscalls/fchownat.S
+syscall_src += arch-mips/syscalls/fchmodat.S
+syscall_src += arch-mips/syscalls/renameat.S
+syscall_src += arch-mips/syscalls/fsetxattr.S
+syscall_src += arch-mips/syscalls/fgetxattr.S
+syscall_src += arch-mips/syscalls/flistxattr.S
+syscall_src += arch-mips/syscalls/fremovexattr.S
+syscall_src += arch-mips/syscalls/link.S
+syscall_src += arch-mips/syscalls/unlink.S
+syscall_src += arch-mips/syscalls/unlinkat.S
+syscall_src += arch-mips/syscalls/chdir.S
+syscall_src += arch-mips/syscalls/mknod.S
+syscall_src += arch-mips/syscalls/chmod.S
+syscall_src += arch-mips/syscalls/chown.S
+syscall_src += arch-mips/syscalls/lchown.S
+syscall_src += arch-mips/syscalls/mount.S
+syscall_src += arch-mips/syscalls/umount2.S
+syscall_src += arch-mips/syscalls/fstat.S
+syscall_src += arch-mips/syscalls/stat.S
+syscall_src += arch-mips/syscalls/lstat.S
+syscall_src += arch-mips/syscalls/mkdir.S
+syscall_src += arch-mips/syscalls/readlink.S
+syscall_src += arch-mips/syscalls/rmdir.S
+syscall_src += arch-mips/syscalls/rename.S
+syscall_src += arch-mips/syscalls/__getcwd.S
+syscall_src += arch-mips/syscalls/access.S
+syscall_src += arch-mips/syscalls/faccessat.S
+syscall_src += arch-mips/syscalls/symlink.S
+syscall_src += arch-mips/syscalls/fchdir.S
+syscall_src += arch-mips/syscalls/truncate.S
+syscall_src += arch-mips/syscalls/setxattr.S
+syscall_src += arch-mips/syscalls/lsetxattr.S
+syscall_src += arch-mips/syscalls/getxattr.S
+syscall_src += arch-mips/syscalls/lgetxattr.S
+syscall_src += arch-mips/syscalls/listxattr.S
+syscall_src += arch-mips/syscalls/llistxattr.S
+syscall_src += arch-mips/syscalls/removexattr.S
+syscall_src += arch-mips/syscalls/lremovexattr.S
+syscall_src += arch-mips/syscalls/__statfs64.S
+syscall_src += arch-mips/syscalls/pause.S
+syscall_src += arch-mips/syscalls/gettimeofday.S
+syscall_src += arch-mips/syscalls/settimeofday.S
+syscall_src += arch-mips/syscalls/times.S
+syscall_src += arch-mips/syscalls/nanosleep.S
+syscall_src += arch-mips/syscalls/clock_gettime.S
+syscall_src += arch-mips/syscalls/clock_settime.S
+syscall_src += arch-mips/syscalls/clock_getres.S
+syscall_src += arch-mips/syscalls/clock_nanosleep.S
+syscall_src += arch-mips/syscalls/getitimer.S
+syscall_src += arch-mips/syscalls/setitimer.S
+syscall_src += arch-mips/syscalls/__timer_create.S
+syscall_src += arch-mips/syscalls/__timer_settime.S
+syscall_src += arch-mips/syscalls/__timer_gettime.S
+syscall_src += arch-mips/syscalls/__timer_getoverrun.S
+syscall_src += arch-mips/syscalls/__timer_delete.S
+syscall_src += arch-mips/syscalls/utimes.S
+syscall_src += arch-mips/syscalls/utimensat.S
+syscall_src += arch-mips/syscalls/sigaction.S
+syscall_src += arch-mips/syscalls/sigprocmask.S
+syscall_src += arch-mips/syscalls/__sigsuspend.S
+syscall_src += arch-mips/syscalls/__rt_sigaction.S
+syscall_src += arch-mips/syscalls/__rt_sigprocmask.S
+syscall_src += arch-mips/syscalls/__rt_sigtimedwait.S
+syscall_src += arch-mips/syscalls/sigpending.S
+syscall_src += arch-mips/syscalls/socket.S
+syscall_src += arch-mips/syscalls/socketpair.S
+syscall_src += arch-mips/syscalls/bind.S
+syscall_src += arch-mips/syscalls/connect.S
+syscall_src += arch-mips/syscalls/listen.S
+syscall_src += arch-mips/syscalls/accept.S
+syscall_src += arch-mips/syscalls/getsockname.S
+syscall_src += arch-mips/syscalls/getpeername.S
+syscall_src += arch-mips/syscalls/sendto.S
+syscall_src += arch-mips/syscalls/recvfrom.S
+syscall_src += arch-mips/syscalls/shutdown.S
+syscall_src += arch-mips/syscalls/setsockopt.S
+syscall_src += arch-mips/syscalls/getsockopt.S
+syscall_src += arch-mips/syscalls/sendmsg.S
+syscall_src += arch-mips/syscalls/recvmsg.S
+syscall_src += arch-mips/syscalls/sched_setscheduler.S
+syscall_src += arch-mips/syscalls/sched_getscheduler.S
+syscall_src += arch-mips/syscalls/sched_yield.S
+syscall_src += arch-mips/syscalls/sched_setparam.S
+syscall_src += arch-mips/syscalls/sched_getparam.S
+syscall_src += arch-mips/syscalls/sched_get_priority_max.S
+syscall_src += arch-mips/syscalls/sched_get_priority_min.S
+syscall_src += arch-mips/syscalls/sched_rr_get_interval.S
+syscall_src += arch-mips/syscalls/sched_setaffinity.S
+syscall_src += arch-mips/syscalls/__sched_getaffinity.S
+syscall_src += arch-mips/syscalls/__getcpu.S
+syscall_src += arch-mips/syscalls/ioprio_set.S
+syscall_src += arch-mips/syscalls/ioprio_get.S
+syscall_src += arch-mips/syscalls/uname.S
+syscall_src += arch-mips/syscalls/__wait4.S
+syscall_src += arch-mips/syscalls/umask.S
+syscall_src += arch-mips/syscalls/__reboot.S
+syscall_src += arch-mips/syscalls/__syslog.S
+syscall_src += arch-mips/syscalls/init_module.S
+syscall_src += arch-mips/syscalls/delete_module.S
+syscall_src += arch-mips/syscalls/klogctl.S
+syscall_src += arch-mips/syscalls/sysinfo.S
+syscall_src += arch-mips/syscalls/personality.S
+syscall_src += arch-mips/syscalls/perf_event_open.S
+syscall_src += arch-mips/syscalls/futex.S
+syscall_src += arch-mips/syscalls/epoll_create.S
+syscall_src += arch-mips/syscalls/epoll_ctl.S
+syscall_src += arch-mips/syscalls/epoll_wait.S
+syscall_src += arch-mips/syscalls/inotify_init.S
+syscall_src += arch-mips/syscalls/inotify_add_watch.S
+syscall_src += arch-mips/syscalls/inotify_rm_watch.S
+syscall_src += arch-mips/syscalls/poll.S
+syscall_src += arch-mips/syscalls/eventfd.S
+syscall_src += arch-mips/syscalls/_flush_cache.S
+syscall_src += arch-mips/syscalls/syscall.S
diff --git a/libc/arch-mips/syscalls/__brk.S b/libc/arch-mips/syscalls/__brk.S
new file mode 100644
index 0000000..1f09772
--- /dev/null
+++ b/libc/arch-mips/syscalls/__brk.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __brk
+    .align 4
+    .ent __brk
+
+__brk:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_brk
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __brk
diff --git a/libc/arch-mips/syscalls/__fcntl.S b/libc/arch-mips/syscalls/__fcntl.S
new file mode 100644
index 0000000..6dd76e3
--- /dev/null
+++ b/libc/arch-mips/syscalls/__fcntl.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __fcntl
+    .align 4
+    .ent __fcntl
+
+__fcntl:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fcntl
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __fcntl
diff --git a/libc/arch-mips/syscalls/__fcntl64.S b/libc/arch-mips/syscalls/__fcntl64.S
new file mode 100644
index 0000000..e82e382
--- /dev/null
+++ b/libc/arch-mips/syscalls/__fcntl64.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __fcntl64
+    .align 4
+    .ent __fcntl64
+
+__fcntl64:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fcntl64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __fcntl64
diff --git a/libc/arch-mips/syscalls/__fork.S b/libc/arch-mips/syscalls/__fork.S
new file mode 100644
index 0000000..db30472
--- /dev/null
+++ b/libc/arch-mips/syscalls/__fork.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __fork
+    .align 4
+    .ent __fork
+
+__fork:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fork
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __fork
diff --git a/libc/arch-mips/syscalls/__fstatfs64.S b/libc/arch-mips/syscalls/__fstatfs64.S
new file mode 100644
index 0000000..6485d10
--- /dev/null
+++ b/libc/arch-mips/syscalls/__fstatfs64.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __fstatfs64
+    .align 4
+    .ent __fstatfs64
+
+__fstatfs64:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fstatfs64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __fstatfs64
diff --git a/libc/arch-mips/syscalls/__getcpu.S b/libc/arch-mips/syscalls/__getcpu.S
new file mode 100644
index 0000000..90d59f4
--- /dev/null
+++ b/libc/arch-mips/syscalls/__getcpu.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __getcpu
+    .align 4
+    .ent __getcpu
+
+__getcpu:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getcpu
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __getcpu
diff --git a/libc/arch-mips/syscalls/__getcwd.S b/libc/arch-mips/syscalls/__getcwd.S
new file mode 100644
index 0000000..e8fa340
--- /dev/null
+++ b/libc/arch-mips/syscalls/__getcwd.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __getcwd
+    .align 4
+    .ent __getcwd
+
+__getcwd:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getcwd
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __getcwd
diff --git a/libc/arch-mips/syscalls/__getpriority.S b/libc/arch-mips/syscalls/__getpriority.S
new file mode 100644
index 0000000..7cabd31
--- /dev/null
+++ b/libc/arch-mips/syscalls/__getpriority.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __getpriority
+    .align 4
+    .ent __getpriority
+
+__getpriority:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getpriority
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __getpriority
diff --git a/libc/arch-mips/syscalls/__ioctl.S b/libc/arch-mips/syscalls/__ioctl.S
new file mode 100644
index 0000000..2524e02
--- /dev/null
+++ b/libc/arch-mips/syscalls/__ioctl.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __ioctl
+    .align 4
+    .ent __ioctl
+
+__ioctl:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_ioctl
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __ioctl
diff --git a/libc/arch-mips/syscalls/__llseek.S b/libc/arch-mips/syscalls/__llseek.S
new file mode 100644
index 0000000..fbfd583
--- /dev/null
+++ b/libc/arch-mips/syscalls/__llseek.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __llseek
+    .align 4
+    .ent __llseek
+
+__llseek:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR__llseek
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __llseek
diff --git a/libc/arch-mips/syscalls/__mmap2.S b/libc/arch-mips/syscalls/__mmap2.S
new file mode 100644
index 0000000..98f97eb
--- /dev/null
+++ b/libc/arch-mips/syscalls/__mmap2.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __mmap2
+    .align 4
+    .ent __mmap2
+
+__mmap2:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mmap2
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __mmap2
diff --git a/libc/arch-mips/syscalls/__open.S b/libc/arch-mips/syscalls/__open.S
new file mode 100644
index 0000000..0ccb286
--- /dev/null
+++ b/libc/arch-mips/syscalls/__open.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __open
+    .align 4
+    .ent __open
+
+__open:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_open
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __open
diff --git a/libc/arch-mips/syscalls/__openat.S b/libc/arch-mips/syscalls/__openat.S
new file mode 100644
index 0000000..04399b4
--- /dev/null
+++ b/libc/arch-mips/syscalls/__openat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __openat
+    .align 4
+    .ent __openat
+
+__openat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_openat
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __openat
diff --git a/libc/arch-mips/syscalls/__ptrace.S b/libc/arch-mips/syscalls/__ptrace.S
new file mode 100644
index 0000000..0bcba9f
--- /dev/null
+++ b/libc/arch-mips/syscalls/__ptrace.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __ptrace
+    .align 4
+    .ent __ptrace
+
+__ptrace:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_ptrace
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __ptrace
diff --git a/libc/arch-mips/syscalls/__reboot.S b/libc/arch-mips/syscalls/__reboot.S
new file mode 100644
index 0000000..5e8e57a
--- /dev/null
+++ b/libc/arch-mips/syscalls/__reboot.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __reboot
+    .align 4
+    .ent __reboot
+
+__reboot:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_reboot
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __reboot
diff --git a/libc/arch-mips/syscalls/__rt_sigaction.S b/libc/arch-mips/syscalls/__rt_sigaction.S
new file mode 100644
index 0000000..43a571a
--- /dev/null
+++ b/libc/arch-mips/syscalls/__rt_sigaction.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __rt_sigaction
+    .align 4
+    .ent __rt_sigaction
+
+__rt_sigaction:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_rt_sigaction
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __rt_sigaction
diff --git a/libc/arch-mips/syscalls/__rt_sigprocmask.S b/libc/arch-mips/syscalls/__rt_sigprocmask.S
new file mode 100644
index 0000000..59a8894
--- /dev/null
+++ b/libc/arch-mips/syscalls/__rt_sigprocmask.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __rt_sigprocmask
+    .align 4
+    .ent __rt_sigprocmask
+
+__rt_sigprocmask:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_rt_sigprocmask
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __rt_sigprocmask
diff --git a/libc/arch-mips/syscalls/__rt_sigtimedwait.S b/libc/arch-mips/syscalls/__rt_sigtimedwait.S
new file mode 100644
index 0000000..dae872e
--- /dev/null
+++ b/libc/arch-mips/syscalls/__rt_sigtimedwait.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __rt_sigtimedwait
+    .align 4
+    .ent __rt_sigtimedwait
+
+__rt_sigtimedwait:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_rt_sigtimedwait
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __rt_sigtimedwait
diff --git a/libc/arch-mips/syscalls/__sched_getaffinity.S b/libc/arch-mips/syscalls/__sched_getaffinity.S
new file mode 100644
index 0000000..cc01ff2
--- /dev/null
+++ b/libc/arch-mips/syscalls/__sched_getaffinity.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __sched_getaffinity
+    .align 4
+    .ent __sched_getaffinity
+
+__sched_getaffinity:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_getaffinity
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __sched_getaffinity
diff --git a/libc/arch-mips/syscalls/__set_thread_area.S b/libc/arch-mips/syscalls/__set_thread_area.S
new file mode 100644
index 0000000..2aac901
--- /dev/null
+++ b/libc/arch-mips/syscalls/__set_thread_area.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __set_thread_area
+    .align 4
+    .ent __set_thread_area
+
+__set_thread_area:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_set_thread_area
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __set_thread_area
diff --git a/libc/arch-mips/syscalls/__setresuid.S b/libc/arch-mips/syscalls/__setresuid.S
new file mode 100644
index 0000000..e00d2e1
--- /dev/null
+++ b/libc/arch-mips/syscalls/__setresuid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __setresuid
+    .align 4
+    .ent __setresuid
+
+__setresuid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setresuid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __setresuid
diff --git a/libc/arch-mips/syscalls/__setreuid.S b/libc/arch-mips/syscalls/__setreuid.S
new file mode 100644
index 0000000..b45f3fc
--- /dev/null
+++ b/libc/arch-mips/syscalls/__setreuid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __setreuid
+    .align 4
+    .ent __setreuid
+
+__setreuid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setreuid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __setreuid
diff --git a/libc/arch-mips/syscalls/__setuid.S b/libc/arch-mips/syscalls/__setuid.S
new file mode 100644
index 0000000..c221526
--- /dev/null
+++ b/libc/arch-mips/syscalls/__setuid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __setuid
+    .align 4
+    .ent __setuid
+
+__setuid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setuid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __setuid
diff --git a/libc/arch-mips/syscalls/__sigsuspend.S b/libc/arch-mips/syscalls/__sigsuspend.S
new file mode 100644
index 0000000..b622efe
--- /dev/null
+++ b/libc/arch-mips/syscalls/__sigsuspend.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __sigsuspend
+    .align 4
+    .ent __sigsuspend
+
+__sigsuspend:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sigsuspend
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __sigsuspend
diff --git a/libc/arch-mips/syscalls/__statfs64.S b/libc/arch-mips/syscalls/__statfs64.S
new file mode 100644
index 0000000..4d1b17f
--- /dev/null
+++ b/libc/arch-mips/syscalls/__statfs64.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __statfs64
+    .align 4
+    .ent __statfs64
+
+__statfs64:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_statfs64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __statfs64
diff --git a/libc/arch-mips/syscalls/__sys_clone.S b/libc/arch-mips/syscalls/__sys_clone.S
new file mode 100644
index 0000000..3451e02
--- /dev/null
+++ b/libc/arch-mips/syscalls/__sys_clone.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __sys_clone
+    .align 4
+    .ent __sys_clone
+
+__sys_clone:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_clone
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __sys_clone
diff --git a/libc/arch-mips/syscalls/__syslog.S b/libc/arch-mips/syscalls/__syslog.S
new file mode 100644
index 0000000..bdc194d
--- /dev/null
+++ b/libc/arch-mips/syscalls/__syslog.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __syslog
+    .align 4
+    .ent __syslog
+
+__syslog:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_syslog
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __syslog
diff --git a/libc/arch-mips/syscalls/__timer_create.S b/libc/arch-mips/syscalls/__timer_create.S
new file mode 100644
index 0000000..140d0d1
--- /dev/null
+++ b/libc/arch-mips/syscalls/__timer_create.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __timer_create
+    .align 4
+    .ent __timer_create
+
+__timer_create:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_timer_create
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __timer_create
diff --git a/libc/arch-mips/syscalls/__timer_delete.S b/libc/arch-mips/syscalls/__timer_delete.S
new file mode 100644
index 0000000..4f362e6
--- /dev/null
+++ b/libc/arch-mips/syscalls/__timer_delete.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __timer_delete
+    .align 4
+    .ent __timer_delete
+
+__timer_delete:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_timer_delete
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __timer_delete
diff --git a/libc/arch-mips/syscalls/__timer_getoverrun.S b/libc/arch-mips/syscalls/__timer_getoverrun.S
new file mode 100644
index 0000000..68afa1c
--- /dev/null
+++ b/libc/arch-mips/syscalls/__timer_getoverrun.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __timer_getoverrun
+    .align 4
+    .ent __timer_getoverrun
+
+__timer_getoverrun:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_timer_getoverrun
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __timer_getoverrun
diff --git a/libc/arch-mips/syscalls/__timer_gettime.S b/libc/arch-mips/syscalls/__timer_gettime.S
new file mode 100644
index 0000000..4a70da6
--- /dev/null
+++ b/libc/arch-mips/syscalls/__timer_gettime.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __timer_gettime
+    .align 4
+    .ent __timer_gettime
+
+__timer_gettime:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_timer_gettime
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __timer_gettime
diff --git a/libc/arch-mips/syscalls/__timer_settime.S b/libc/arch-mips/syscalls/__timer_settime.S
new file mode 100644
index 0000000..ad84606
--- /dev/null
+++ b/libc/arch-mips/syscalls/__timer_settime.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __timer_settime
+    .align 4
+    .ent __timer_settime
+
+__timer_settime:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_timer_settime
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __timer_settime
diff --git a/libc/arch-mips/syscalls/__wait4.S b/libc/arch-mips/syscalls/__wait4.S
new file mode 100644
index 0000000..713b7cb
--- /dev/null
+++ b/libc/arch-mips/syscalls/__wait4.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __wait4
+    .align 4
+    .ent __wait4
+
+__wait4:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_wait4
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __wait4
diff --git a/libc/arch-mips/syscalls/__waitid.S b/libc/arch-mips/syscalls/__waitid.S
new file mode 100644
index 0000000..83e5aa3
--- /dev/null
+++ b/libc/arch-mips/syscalls/__waitid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl __waitid
+    .align 4
+    .ent __waitid
+
+__waitid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_waitid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end __waitid
diff --git a/libc/arch-mips/syscalls/_exit.S b/libc/arch-mips/syscalls/_exit.S
new file mode 100644
index 0000000..b7ec876
--- /dev/null
+++ b/libc/arch-mips/syscalls/_exit.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl _exit
+    .align 4
+    .ent _exit
+
+_exit:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_exit_group
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end _exit
diff --git a/libc/arch-mips/syscalls/_exit_thread.S b/libc/arch-mips/syscalls/_exit_thread.S
new file mode 100644
index 0000000..0af9d3d
--- /dev/null
+++ b/libc/arch-mips/syscalls/_exit_thread.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl _exit_thread
+    .align 4
+    .ent _exit_thread
+
+_exit_thread:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_exit
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end _exit_thread
diff --git a/libc/arch-mips/syscalls/_flush_cache.S b/libc/arch-mips/syscalls/_flush_cache.S
new file mode 100644
index 0000000..07dee66
--- /dev/null
+++ b/libc/arch-mips/syscalls/_flush_cache.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl _flush_cache
+    .align 4
+    .ent _flush_cache
+
+_flush_cache:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_cacheflush
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end _flush_cache
diff --git a/libc/arch-mips/syscalls/_waitpid.S b/libc/arch-mips/syscalls/_waitpid.S
new file mode 100644
index 0000000..20db3a8
--- /dev/null
+++ b/libc/arch-mips/syscalls/_waitpid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl _waitpid
+    .align 4
+    .ent _waitpid
+
+_waitpid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_waitpid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end _waitpid
diff --git a/libc/arch-mips/syscalls/accept.S b/libc/arch-mips/syscalls/accept.S
new file mode 100644
index 0000000..c19216e
--- /dev/null
+++ b/libc/arch-mips/syscalls/accept.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl accept
+    .align 4
+    .ent accept
+
+accept:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_accept
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end accept
diff --git a/libc/arch-mips/syscalls/access.S b/libc/arch-mips/syscalls/access.S
new file mode 100644
index 0000000..a22ed92
--- /dev/null
+++ b/libc/arch-mips/syscalls/access.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl access
+    .align 4
+    .ent access
+
+access:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_access
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end access
diff --git a/libc/arch-mips/syscalls/acct.S b/libc/arch-mips/syscalls/acct.S
new file mode 100644
index 0000000..5235ede
--- /dev/null
+++ b/libc/arch-mips/syscalls/acct.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl acct
+    .align 4
+    .ent acct
+
+acct:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_acct
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end acct
diff --git a/libc/arch-mips/syscalls/bind.S b/libc/arch-mips/syscalls/bind.S
new file mode 100644
index 0000000..4f00922
--- /dev/null
+++ b/libc/arch-mips/syscalls/bind.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl bind
+    .align 4
+    .ent bind
+
+bind:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_bind
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end bind
diff --git a/libc/arch-mips/syscalls/capget.S b/libc/arch-mips/syscalls/capget.S
new file mode 100644
index 0000000..80e55ee
--- /dev/null
+++ b/libc/arch-mips/syscalls/capget.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl capget
+    .align 4
+    .ent capget
+
+capget:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_capget
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end capget
diff --git a/libc/arch-mips/syscalls/capset.S b/libc/arch-mips/syscalls/capset.S
new file mode 100644
index 0000000..0e4a3be
--- /dev/null
+++ b/libc/arch-mips/syscalls/capset.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl capset
+    .align 4
+    .ent capset
+
+capset:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_capset
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end capset
diff --git a/libc/arch-mips/syscalls/chdir.S b/libc/arch-mips/syscalls/chdir.S
new file mode 100644
index 0000000..42eb37c
--- /dev/null
+++ b/libc/arch-mips/syscalls/chdir.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl chdir
+    .align 4
+    .ent chdir
+
+chdir:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_chdir
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end chdir
diff --git a/libc/arch-mips/syscalls/chmod.S b/libc/arch-mips/syscalls/chmod.S
new file mode 100644
index 0000000..7ea3ede
--- /dev/null
+++ b/libc/arch-mips/syscalls/chmod.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl chmod
+    .align 4
+    .ent chmod
+
+chmod:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_chmod
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end chmod
diff --git a/libc/arch-mips/syscalls/chown.S b/libc/arch-mips/syscalls/chown.S
new file mode 100644
index 0000000..5fb1e32
--- /dev/null
+++ b/libc/arch-mips/syscalls/chown.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl chown
+    .align 4
+    .ent chown
+
+chown:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_chown
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end chown
diff --git a/libc/arch-mips/syscalls/chroot.S b/libc/arch-mips/syscalls/chroot.S
new file mode 100644
index 0000000..fafb6a2
--- /dev/null
+++ b/libc/arch-mips/syscalls/chroot.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl chroot
+    .align 4
+    .ent chroot
+
+chroot:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_chroot
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end chroot
diff --git a/libc/arch-mips/syscalls/clock_getres.S b/libc/arch-mips/syscalls/clock_getres.S
new file mode 100644
index 0000000..4021b14
--- /dev/null
+++ b/libc/arch-mips/syscalls/clock_getres.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl clock_getres
+    .align 4
+    .ent clock_getres
+
+clock_getres:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_clock_getres
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end clock_getres
diff --git a/libc/arch-mips/syscalls/clock_gettime.S b/libc/arch-mips/syscalls/clock_gettime.S
new file mode 100644
index 0000000..ba7afb9
--- /dev/null
+++ b/libc/arch-mips/syscalls/clock_gettime.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl clock_gettime
+    .align 4
+    .ent clock_gettime
+
+clock_gettime:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_clock_gettime
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end clock_gettime
diff --git a/libc/arch-mips/syscalls/clock_nanosleep.S b/libc/arch-mips/syscalls/clock_nanosleep.S
new file mode 100644
index 0000000..1a9aef5
--- /dev/null
+++ b/libc/arch-mips/syscalls/clock_nanosleep.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl clock_nanosleep
+    .align 4
+    .ent clock_nanosleep
+
+clock_nanosleep:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_clock_nanosleep
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end clock_nanosleep
diff --git a/libc/arch-mips/syscalls/clock_settime.S b/libc/arch-mips/syscalls/clock_settime.S
new file mode 100644
index 0000000..65d4388
--- /dev/null
+++ b/libc/arch-mips/syscalls/clock_settime.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl clock_settime
+    .align 4
+    .ent clock_settime
+
+clock_settime:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_clock_settime
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end clock_settime
diff --git a/libc/arch-mips/syscalls/close.S b/libc/arch-mips/syscalls/close.S
new file mode 100644
index 0000000..07ff4e3
--- /dev/null
+++ b/libc/arch-mips/syscalls/close.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl close
+    .align 4
+    .ent close
+
+close:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_close
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end close
diff --git a/libc/arch-mips/syscalls/connect.S b/libc/arch-mips/syscalls/connect.S
new file mode 100644
index 0000000..d1fc280
--- /dev/null
+++ b/libc/arch-mips/syscalls/connect.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl connect
+    .align 4
+    .ent connect
+
+connect:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_connect
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end connect
diff --git a/libc/arch-mips/syscalls/delete_module.S b/libc/arch-mips/syscalls/delete_module.S
new file mode 100644
index 0000000..db80ba7
--- /dev/null
+++ b/libc/arch-mips/syscalls/delete_module.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl delete_module
+    .align 4
+    .ent delete_module
+
+delete_module:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_delete_module
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end delete_module
diff --git a/libc/arch-mips/syscalls/dup.S b/libc/arch-mips/syscalls/dup.S
new file mode 100644
index 0000000..e815749
--- /dev/null
+++ b/libc/arch-mips/syscalls/dup.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl dup
+    .align 4
+    .ent dup
+
+dup:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_dup
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end dup
diff --git a/libc/arch-mips/syscalls/dup2.S b/libc/arch-mips/syscalls/dup2.S
new file mode 100644
index 0000000..6fb151f
--- /dev/null
+++ b/libc/arch-mips/syscalls/dup2.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl dup2
+    .align 4
+    .ent dup2
+
+dup2:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_dup2
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end dup2
diff --git a/libc/arch-mips/syscalls/epoll_create.S b/libc/arch-mips/syscalls/epoll_create.S
new file mode 100644
index 0000000..e5e420b
--- /dev/null
+++ b/libc/arch-mips/syscalls/epoll_create.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl epoll_create
+    .align 4
+    .ent epoll_create
+
+epoll_create:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_epoll_create
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end epoll_create
diff --git a/libc/arch-mips/syscalls/epoll_ctl.S b/libc/arch-mips/syscalls/epoll_ctl.S
new file mode 100644
index 0000000..f4f9f05
--- /dev/null
+++ b/libc/arch-mips/syscalls/epoll_ctl.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl epoll_ctl
+    .align 4
+    .ent epoll_ctl
+
+epoll_ctl:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_epoll_ctl
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end epoll_ctl
diff --git a/libc/arch-mips/syscalls/epoll_wait.S b/libc/arch-mips/syscalls/epoll_wait.S
new file mode 100644
index 0000000..64d33fb
--- /dev/null
+++ b/libc/arch-mips/syscalls/epoll_wait.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl epoll_wait
+    .align 4
+    .ent epoll_wait
+
+epoll_wait:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_epoll_wait
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end epoll_wait
diff --git a/libc/arch-mips/syscalls/eventfd.S b/libc/arch-mips/syscalls/eventfd.S
new file mode 100644
index 0000000..5c4e22b
--- /dev/null
+++ b/libc/arch-mips/syscalls/eventfd.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl eventfd
+    .align 4
+    .ent eventfd
+
+eventfd:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_eventfd2
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end eventfd
diff --git a/libc/arch-mips/syscalls/execve.S b/libc/arch-mips/syscalls/execve.S
new file mode 100644
index 0000000..31b9276
--- /dev/null
+++ b/libc/arch-mips/syscalls/execve.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl execve
+    .align 4
+    .ent execve
+
+execve:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_execve
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end execve
diff --git a/libc/arch-mips/syscalls/faccessat.S b/libc/arch-mips/syscalls/faccessat.S
new file mode 100644
index 0000000..97db4c0
--- /dev/null
+++ b/libc/arch-mips/syscalls/faccessat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl faccessat
+    .align 4
+    .ent faccessat
+
+faccessat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_faccessat
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end faccessat
diff --git a/libc/arch-mips/syscalls/fchdir.S b/libc/arch-mips/syscalls/fchdir.S
new file mode 100644
index 0000000..93298bd
--- /dev/null
+++ b/libc/arch-mips/syscalls/fchdir.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fchdir
+    .align 4
+    .ent fchdir
+
+fchdir:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fchdir
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fchdir
diff --git a/libc/arch-mips/syscalls/fchmod.S b/libc/arch-mips/syscalls/fchmod.S
new file mode 100644
index 0000000..f483567
--- /dev/null
+++ b/libc/arch-mips/syscalls/fchmod.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fchmod
+    .align 4
+    .ent fchmod
+
+fchmod:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fchmod
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fchmod
diff --git a/libc/arch-mips/syscalls/fchmodat.S b/libc/arch-mips/syscalls/fchmodat.S
new file mode 100644
index 0000000..8ba1bbe
--- /dev/null
+++ b/libc/arch-mips/syscalls/fchmodat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fchmodat
+    .align 4
+    .ent fchmodat
+
+fchmodat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fchmodat
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fchmodat
diff --git a/libc/arch-mips/syscalls/fchown.S b/libc/arch-mips/syscalls/fchown.S
new file mode 100644
index 0000000..24fc08f
--- /dev/null
+++ b/libc/arch-mips/syscalls/fchown.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fchown
+    .align 4
+    .ent fchown
+
+fchown:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fchown
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fchown
diff --git a/libc/arch-mips/syscalls/fchownat.S b/libc/arch-mips/syscalls/fchownat.S
new file mode 100644
index 0000000..983ed56
--- /dev/null
+++ b/libc/arch-mips/syscalls/fchownat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fchownat
+    .align 4
+    .ent fchownat
+
+fchownat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fchownat
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fchownat
diff --git a/libc/arch-mips/syscalls/fdatasync.S b/libc/arch-mips/syscalls/fdatasync.S
new file mode 100644
index 0000000..312439d
--- /dev/null
+++ b/libc/arch-mips/syscalls/fdatasync.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fdatasync
+    .align 4
+    .ent fdatasync
+
+fdatasync:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fdatasync
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fdatasync
diff --git a/libc/arch-mips/syscalls/fgetxattr.S b/libc/arch-mips/syscalls/fgetxattr.S
new file mode 100644
index 0000000..7e77e61
--- /dev/null
+++ b/libc/arch-mips/syscalls/fgetxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fgetxattr
+    .align 4
+    .ent fgetxattr
+
+fgetxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fgetxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fgetxattr
diff --git a/libc/arch-mips/syscalls/flistxattr.S b/libc/arch-mips/syscalls/flistxattr.S
new file mode 100644
index 0000000..26e26e1
--- /dev/null
+++ b/libc/arch-mips/syscalls/flistxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl flistxattr
+    .align 4
+    .ent flistxattr
+
+flistxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_flistxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end flistxattr
diff --git a/libc/arch-mips/syscalls/flock.S b/libc/arch-mips/syscalls/flock.S
new file mode 100644
index 0000000..f9a3142
--- /dev/null
+++ b/libc/arch-mips/syscalls/flock.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl flock
+    .align 4
+    .ent flock
+
+flock:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_flock
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end flock
diff --git a/libc/arch-mips/syscalls/fremovexattr.S b/libc/arch-mips/syscalls/fremovexattr.S
new file mode 100644
index 0000000..db3eb6c
--- /dev/null
+++ b/libc/arch-mips/syscalls/fremovexattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fremovexattr
+    .align 4
+    .ent fremovexattr
+
+fremovexattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fremovexattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fremovexattr
diff --git a/libc/arch-mips/syscalls/fsetxattr.S b/libc/arch-mips/syscalls/fsetxattr.S
new file mode 100644
index 0000000..9e666f2
--- /dev/null
+++ b/libc/arch-mips/syscalls/fsetxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fsetxattr
+    .align 4
+    .ent fsetxattr
+
+fsetxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fsetxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fsetxattr
diff --git a/libc/arch-mips/syscalls/fstat.S b/libc/arch-mips/syscalls/fstat.S
new file mode 100644
index 0000000..73d7235
--- /dev/null
+++ b/libc/arch-mips/syscalls/fstat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fstat
+    .align 4
+    .ent fstat
+
+fstat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fstat64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fstat
diff --git a/libc/arch-mips/syscalls/fstatat.S b/libc/arch-mips/syscalls/fstatat.S
new file mode 100644
index 0000000..3ae229e
--- /dev/null
+++ b/libc/arch-mips/syscalls/fstatat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fstatat
+    .align 4
+    .ent fstatat
+
+fstatat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fstatat64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fstatat
diff --git a/libc/arch-mips/syscalls/fsync.S b/libc/arch-mips/syscalls/fsync.S
new file mode 100644
index 0000000..e1cd316
--- /dev/null
+++ b/libc/arch-mips/syscalls/fsync.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl fsync
+    .align 4
+    .ent fsync
+
+fsync:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fsync
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fsync
diff --git a/libc/arch-mips/syscalls/ftruncate.S b/libc/arch-mips/syscalls/ftruncate.S
new file mode 100644
index 0000000..5d72b43
--- /dev/null
+++ b/libc/arch-mips/syscalls/ftruncate.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl ftruncate
+    .align 4
+    .ent ftruncate
+
+ftruncate:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_ftruncate
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end ftruncate
diff --git a/libc/arch-mips/syscalls/ftruncate64.S b/libc/arch-mips/syscalls/ftruncate64.S
new file mode 100644
index 0000000..216ae38
--- /dev/null
+++ b/libc/arch-mips/syscalls/ftruncate64.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl ftruncate64
+    .align 4
+    .ent ftruncate64
+
+ftruncate64:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_ftruncate64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end ftruncate64
diff --git a/libc/arch-mips/syscalls/futex.S b/libc/arch-mips/syscalls/futex.S
new file mode 100644
index 0000000..65e537a
--- /dev/null
+++ b/libc/arch-mips/syscalls/futex.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl futex
+    .align 4
+    .ent futex
+
+futex:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_futex
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end futex
diff --git a/libc/arch-mips/syscalls/getdents.S b/libc/arch-mips/syscalls/getdents.S
new file mode 100644
index 0000000..8ff0f26
--- /dev/null
+++ b/libc/arch-mips/syscalls/getdents.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getdents
+    .align 4
+    .ent getdents
+
+getdents:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getdents64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getdents
diff --git a/libc/arch-mips/syscalls/getegid.S b/libc/arch-mips/syscalls/getegid.S
new file mode 100644
index 0000000..dc2a04b
--- /dev/null
+++ b/libc/arch-mips/syscalls/getegid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getegid
+    .align 4
+    .ent getegid
+
+getegid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getegid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getegid
diff --git a/libc/arch-mips/syscalls/geteuid.S b/libc/arch-mips/syscalls/geteuid.S
new file mode 100644
index 0000000..8beca88
--- /dev/null
+++ b/libc/arch-mips/syscalls/geteuid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl geteuid
+    .align 4
+    .ent geteuid
+
+geteuid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_geteuid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end geteuid
diff --git a/libc/arch-mips/syscalls/getgid.S b/libc/arch-mips/syscalls/getgid.S
new file mode 100644
index 0000000..6a615ee
--- /dev/null
+++ b/libc/arch-mips/syscalls/getgid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getgid
+    .align 4
+    .ent getgid
+
+getgid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getgid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getgid
diff --git a/libc/arch-mips/syscalls/getgroups.S b/libc/arch-mips/syscalls/getgroups.S
new file mode 100644
index 0000000..8be7308
--- /dev/null
+++ b/libc/arch-mips/syscalls/getgroups.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getgroups
+    .align 4
+    .ent getgroups
+
+getgroups:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getgroups
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getgroups
diff --git a/libc/arch-mips/syscalls/getitimer.S b/libc/arch-mips/syscalls/getitimer.S
new file mode 100644
index 0000000..3df1d11
--- /dev/null
+++ b/libc/arch-mips/syscalls/getitimer.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getitimer
+    .align 4
+    .ent getitimer
+
+getitimer:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getitimer
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getitimer
diff --git a/libc/arch-mips/syscalls/getpeername.S b/libc/arch-mips/syscalls/getpeername.S
new file mode 100644
index 0000000..4a3beda
--- /dev/null
+++ b/libc/arch-mips/syscalls/getpeername.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getpeername
+    .align 4
+    .ent getpeername
+
+getpeername:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getpeername
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getpeername
diff --git a/libc/arch-mips/syscalls/getpgid.S b/libc/arch-mips/syscalls/getpgid.S
new file mode 100644
index 0000000..fd79351
--- /dev/null
+++ b/libc/arch-mips/syscalls/getpgid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getpgid
+    .align 4
+    .ent getpgid
+
+getpgid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getpgid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getpgid
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/getpid.S
new file mode 100644
index 0000000..f52e31b
--- /dev/null
+++ b/libc/arch-mips/syscalls/getpid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getpid
+    .align 4
+    .ent getpid
+
+getpid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getpid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getpid
diff --git a/libc/arch-mips/syscalls/getppid.S b/libc/arch-mips/syscalls/getppid.S
new file mode 100644
index 0000000..5e3fe19
--- /dev/null
+++ b/libc/arch-mips/syscalls/getppid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getppid
+    .align 4
+    .ent getppid
+
+getppid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getppid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getppid
diff --git a/libc/arch-mips/syscalls/getresgid.S b/libc/arch-mips/syscalls/getresgid.S
new file mode 100644
index 0000000..8e9bf39
--- /dev/null
+++ b/libc/arch-mips/syscalls/getresgid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getresgid
+    .align 4
+    .ent getresgid
+
+getresgid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getresgid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getresgid
diff --git a/libc/arch-mips/syscalls/getresuid.S b/libc/arch-mips/syscalls/getresuid.S
new file mode 100644
index 0000000..ff27cde
--- /dev/null
+++ b/libc/arch-mips/syscalls/getresuid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getresuid
+    .align 4
+    .ent getresuid
+
+getresuid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getresuid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getresuid
diff --git a/libc/arch-mips/syscalls/getrlimit.S b/libc/arch-mips/syscalls/getrlimit.S
new file mode 100644
index 0000000..72ed7d8
--- /dev/null
+++ b/libc/arch-mips/syscalls/getrlimit.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getrlimit
+    .align 4
+    .ent getrlimit
+
+getrlimit:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getrlimit
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getrlimit
diff --git a/libc/arch-mips/syscalls/getrusage.S b/libc/arch-mips/syscalls/getrusage.S
new file mode 100644
index 0000000..4c0f7d0
--- /dev/null
+++ b/libc/arch-mips/syscalls/getrusage.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getrusage
+    .align 4
+    .ent getrusage
+
+getrusage:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getrusage
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getrusage
diff --git a/libc/arch-mips/syscalls/getsockname.S b/libc/arch-mips/syscalls/getsockname.S
new file mode 100644
index 0000000..e3d41f9
--- /dev/null
+++ b/libc/arch-mips/syscalls/getsockname.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getsockname
+    .align 4
+    .ent getsockname
+
+getsockname:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getsockname
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getsockname
diff --git a/libc/arch-mips/syscalls/getsockopt.S b/libc/arch-mips/syscalls/getsockopt.S
new file mode 100644
index 0000000..d55ae6a
--- /dev/null
+++ b/libc/arch-mips/syscalls/getsockopt.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getsockopt
+    .align 4
+    .ent getsockopt
+
+getsockopt:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getsockopt
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getsockopt
diff --git a/libc/arch-mips/syscalls/gettid.S b/libc/arch-mips/syscalls/gettid.S
new file mode 100644
index 0000000..de37df5
--- /dev/null
+++ b/libc/arch-mips/syscalls/gettid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl gettid
+    .align 4
+    .ent gettid
+
+gettid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_gettid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end gettid
diff --git a/libc/arch-mips/syscalls/gettimeofday.S b/libc/arch-mips/syscalls/gettimeofday.S
new file mode 100644
index 0000000..a9a93a5
--- /dev/null
+++ b/libc/arch-mips/syscalls/gettimeofday.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl gettimeofday
+    .align 4
+    .ent gettimeofday
+
+gettimeofday:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_gettimeofday
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end gettimeofday
diff --git a/libc/arch-mips/syscalls/getuid.S b/libc/arch-mips/syscalls/getuid.S
new file mode 100644
index 0000000..e5ba698
--- /dev/null
+++ b/libc/arch-mips/syscalls/getuid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getuid
+    .align 4
+    .ent getuid
+
+getuid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getuid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getuid
diff --git a/libc/arch-mips/syscalls/getxattr.S b/libc/arch-mips/syscalls/getxattr.S
new file mode 100644
index 0000000..6c70579
--- /dev/null
+++ b/libc/arch-mips/syscalls/getxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl getxattr
+    .align 4
+    .ent getxattr
+
+getxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_getxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end getxattr
diff --git a/libc/arch-mips/syscalls/init_module.S b/libc/arch-mips/syscalls/init_module.S
new file mode 100644
index 0000000..5cfbd2f
--- /dev/null
+++ b/libc/arch-mips/syscalls/init_module.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl init_module
+    .align 4
+    .ent init_module
+
+init_module:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_init_module
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end init_module
diff --git a/libc/arch-mips/syscalls/inotify_add_watch.S b/libc/arch-mips/syscalls/inotify_add_watch.S
new file mode 100644
index 0000000..8dde667
--- /dev/null
+++ b/libc/arch-mips/syscalls/inotify_add_watch.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl inotify_add_watch
+    .align 4
+    .ent inotify_add_watch
+
+inotify_add_watch:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_inotify_add_watch
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end inotify_add_watch
diff --git a/libc/arch-mips/syscalls/inotify_init.S b/libc/arch-mips/syscalls/inotify_init.S
new file mode 100644
index 0000000..cde4667
--- /dev/null
+++ b/libc/arch-mips/syscalls/inotify_init.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl inotify_init
+    .align 4
+    .ent inotify_init
+
+inotify_init:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_inotify_init
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end inotify_init
diff --git a/libc/arch-mips/syscalls/inotify_rm_watch.S b/libc/arch-mips/syscalls/inotify_rm_watch.S
new file mode 100644
index 0000000..1b2964e
--- /dev/null
+++ b/libc/arch-mips/syscalls/inotify_rm_watch.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl inotify_rm_watch
+    .align 4
+    .ent inotify_rm_watch
+
+inotify_rm_watch:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_inotify_rm_watch
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end inotify_rm_watch
diff --git a/libc/arch-mips/syscalls/ioprio_get.S b/libc/arch-mips/syscalls/ioprio_get.S
new file mode 100644
index 0000000..f7f2441
--- /dev/null
+++ b/libc/arch-mips/syscalls/ioprio_get.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl ioprio_get
+    .align 4
+    .ent ioprio_get
+
+ioprio_get:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_ioprio_get
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end ioprio_get
diff --git a/libc/arch-mips/syscalls/ioprio_set.S b/libc/arch-mips/syscalls/ioprio_set.S
new file mode 100644
index 0000000..33a30e7
--- /dev/null
+++ b/libc/arch-mips/syscalls/ioprio_set.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl ioprio_set
+    .align 4
+    .ent ioprio_set
+
+ioprio_set:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_ioprio_set
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end ioprio_set
diff --git a/libc/arch-mips/syscalls/kill.S b/libc/arch-mips/syscalls/kill.S
new file mode 100644
index 0000000..a6640ff
--- /dev/null
+++ b/libc/arch-mips/syscalls/kill.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl kill
+    .align 4
+    .ent kill
+
+kill:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_kill
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end kill
diff --git a/libc/arch-mips/syscalls/klogctl.S b/libc/arch-mips/syscalls/klogctl.S
new file mode 100644
index 0000000..8c41dcf
--- /dev/null
+++ b/libc/arch-mips/syscalls/klogctl.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl klogctl
+    .align 4
+    .ent klogctl
+
+klogctl:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_syslog
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end klogctl
diff --git a/libc/arch-mips/syscalls/lchown.S b/libc/arch-mips/syscalls/lchown.S
new file mode 100644
index 0000000..9fb4660
--- /dev/null
+++ b/libc/arch-mips/syscalls/lchown.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl lchown
+    .align 4
+    .ent lchown
+
+lchown:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_lchown
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end lchown
diff --git a/libc/arch-mips/syscalls/lgetxattr.S b/libc/arch-mips/syscalls/lgetxattr.S
new file mode 100644
index 0000000..d546d28
--- /dev/null
+++ b/libc/arch-mips/syscalls/lgetxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl lgetxattr
+    .align 4
+    .ent lgetxattr
+
+lgetxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_lgetxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end lgetxattr
diff --git a/libc/arch-mips/syscalls/link.S b/libc/arch-mips/syscalls/link.S
new file mode 100644
index 0000000..4096b44
--- /dev/null
+++ b/libc/arch-mips/syscalls/link.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl link
+    .align 4
+    .ent link
+
+link:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_link
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end link
diff --git a/libc/arch-mips/syscalls/listen.S b/libc/arch-mips/syscalls/listen.S
new file mode 100644
index 0000000..f365d1d
--- /dev/null
+++ b/libc/arch-mips/syscalls/listen.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl listen
+    .align 4
+    .ent listen
+
+listen:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_listen
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end listen
diff --git a/libc/arch-mips/syscalls/listxattr.S b/libc/arch-mips/syscalls/listxattr.S
new file mode 100644
index 0000000..90b4544
--- /dev/null
+++ b/libc/arch-mips/syscalls/listxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl listxattr
+    .align 4
+    .ent listxattr
+
+listxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_listxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end listxattr
diff --git a/libc/arch-mips/syscalls/llistxattr.S b/libc/arch-mips/syscalls/llistxattr.S
new file mode 100644
index 0000000..e74bf85
--- /dev/null
+++ b/libc/arch-mips/syscalls/llistxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl llistxattr
+    .align 4
+    .ent llistxattr
+
+llistxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_llistxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end llistxattr
diff --git a/libc/arch-mips/syscalls/lremovexattr.S b/libc/arch-mips/syscalls/lremovexattr.S
new file mode 100644
index 0000000..a8d8df9
--- /dev/null
+++ b/libc/arch-mips/syscalls/lremovexattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl lremovexattr
+    .align 4
+    .ent lremovexattr
+
+lremovexattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_lremovexattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end lremovexattr
diff --git a/libc/arch-mips/syscalls/lseek.S b/libc/arch-mips/syscalls/lseek.S
new file mode 100644
index 0000000..bf486ac
--- /dev/null
+++ b/libc/arch-mips/syscalls/lseek.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl lseek
+    .align 4
+    .ent lseek
+
+lseek:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_lseek
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end lseek
diff --git a/libc/arch-mips/syscalls/lsetxattr.S b/libc/arch-mips/syscalls/lsetxattr.S
new file mode 100644
index 0000000..19a0fdf
--- /dev/null
+++ b/libc/arch-mips/syscalls/lsetxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl lsetxattr
+    .align 4
+    .ent lsetxattr
+
+lsetxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_lsetxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end lsetxattr
diff --git a/libc/arch-mips/syscalls/lstat.S b/libc/arch-mips/syscalls/lstat.S
new file mode 100644
index 0000000..355d1da
--- /dev/null
+++ b/libc/arch-mips/syscalls/lstat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl lstat
+    .align 4
+    .ent lstat
+
+lstat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_lstat64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end lstat
diff --git a/libc/arch-mips/syscalls/madvise.S b/libc/arch-mips/syscalls/madvise.S
new file mode 100644
index 0000000..4df7325
--- /dev/null
+++ b/libc/arch-mips/syscalls/madvise.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl madvise
+    .align 4
+    .ent madvise
+
+madvise:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_madvise
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end madvise
diff --git a/libc/arch-mips/syscalls/mincore.S b/libc/arch-mips/syscalls/mincore.S
new file mode 100644
index 0000000..8f467cd
--- /dev/null
+++ b/libc/arch-mips/syscalls/mincore.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl mincore
+    .align 4
+    .ent mincore
+
+mincore:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mincore
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end mincore
diff --git a/libc/arch-mips/syscalls/mkdir.S b/libc/arch-mips/syscalls/mkdir.S
new file mode 100644
index 0000000..abf7db8
--- /dev/null
+++ b/libc/arch-mips/syscalls/mkdir.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl mkdir
+    .align 4
+    .ent mkdir
+
+mkdir:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mkdir
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end mkdir
diff --git a/libc/arch-mips/syscalls/mkdirat.S b/libc/arch-mips/syscalls/mkdirat.S
new file mode 100644
index 0000000..4ccbe3b
--- /dev/null
+++ b/libc/arch-mips/syscalls/mkdirat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl mkdirat
+    .align 4
+    .ent mkdirat
+
+mkdirat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mkdirat
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end mkdirat
diff --git a/libc/arch-mips/syscalls/mknod.S b/libc/arch-mips/syscalls/mknod.S
new file mode 100644
index 0000000..5ebb0ad
--- /dev/null
+++ b/libc/arch-mips/syscalls/mknod.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl mknod
+    .align 4
+    .ent mknod
+
+mknod:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mknod
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end mknod
diff --git a/libc/arch-mips/syscalls/mlock.S b/libc/arch-mips/syscalls/mlock.S
new file mode 100644
index 0000000..99aca6e
--- /dev/null
+++ b/libc/arch-mips/syscalls/mlock.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl mlock
+    .align 4
+    .ent mlock
+
+mlock:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mlock
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end mlock
diff --git a/libc/arch-mips/syscalls/mount.S b/libc/arch-mips/syscalls/mount.S
new file mode 100644
index 0000000..1b3385a
--- /dev/null
+++ b/libc/arch-mips/syscalls/mount.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl mount
+    .align 4
+    .ent mount
+
+mount:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mount
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end mount
diff --git a/libc/arch-mips/syscalls/mprotect.S b/libc/arch-mips/syscalls/mprotect.S
new file mode 100644
index 0000000..4dc3bea
--- /dev/null
+++ b/libc/arch-mips/syscalls/mprotect.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl mprotect
+    .align 4
+    .ent mprotect
+
+mprotect:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mprotect
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end mprotect
diff --git a/libc/arch-mips/syscalls/mremap.S b/libc/arch-mips/syscalls/mremap.S
new file mode 100644
index 0000000..721ccd9
--- /dev/null
+++ b/libc/arch-mips/syscalls/mremap.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl mremap
+    .align 4
+    .ent mremap
+
+mremap:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_mremap
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end mremap
diff --git a/libc/arch-mips/syscalls/msync.S b/libc/arch-mips/syscalls/msync.S
new file mode 100644
index 0000000..37e1c9a
--- /dev/null
+++ b/libc/arch-mips/syscalls/msync.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl msync
+    .align 4
+    .ent msync
+
+msync:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_msync
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end msync
diff --git a/libc/arch-mips/syscalls/munlock.S b/libc/arch-mips/syscalls/munlock.S
new file mode 100644
index 0000000..befc282
--- /dev/null
+++ b/libc/arch-mips/syscalls/munlock.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl munlock
+    .align 4
+    .ent munlock
+
+munlock:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_munlock
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end munlock
diff --git a/libc/arch-mips/syscalls/munmap.S b/libc/arch-mips/syscalls/munmap.S
new file mode 100644
index 0000000..5b717a9
--- /dev/null
+++ b/libc/arch-mips/syscalls/munmap.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl munmap
+    .align 4
+    .ent munmap
+
+munmap:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_munmap
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end munmap
diff --git a/libc/arch-mips/syscalls/nanosleep.S b/libc/arch-mips/syscalls/nanosleep.S
new file mode 100644
index 0000000..58ace12
--- /dev/null
+++ b/libc/arch-mips/syscalls/nanosleep.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl nanosleep
+    .align 4
+    .ent nanosleep
+
+nanosleep:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_nanosleep
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end nanosleep
diff --git a/libc/arch-mips/syscalls/pause.S b/libc/arch-mips/syscalls/pause.S
new file mode 100644
index 0000000..70346b4
--- /dev/null
+++ b/libc/arch-mips/syscalls/pause.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl pause
+    .align 4
+    .ent pause
+
+pause:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_pause
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end pause
diff --git a/libc/arch-mips/syscalls/perf_event_open.S b/libc/arch-mips/syscalls/perf_event_open.S
new file mode 100644
index 0000000..22c9c3c
--- /dev/null
+++ b/libc/arch-mips/syscalls/perf_event_open.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl perf_event_open
+    .align 4
+    .ent perf_event_open
+
+perf_event_open:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_perf_event_open
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end perf_event_open
diff --git a/libc/arch-mips/syscalls/personality.S b/libc/arch-mips/syscalls/personality.S
new file mode 100644
index 0000000..0020469
--- /dev/null
+++ b/libc/arch-mips/syscalls/personality.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl personality
+    .align 4
+    .ent personality
+
+personality:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_personality
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end personality
diff --git a/libc/arch-mips/syscalls/pipe2.S b/libc/arch-mips/syscalls/pipe2.S
new file mode 100644
index 0000000..9dfde29
--- /dev/null
+++ b/libc/arch-mips/syscalls/pipe2.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl pipe2
+    .align 4
+    .ent pipe2
+
+pipe2:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_pipe2
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end pipe2
diff --git a/libc/arch-mips/syscalls/poll.S b/libc/arch-mips/syscalls/poll.S
new file mode 100644
index 0000000..c1fec97
--- /dev/null
+++ b/libc/arch-mips/syscalls/poll.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl poll
+    .align 4
+    .ent poll
+
+poll:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_poll
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end poll
diff --git a/libc/arch-mips/syscalls/prctl.S b/libc/arch-mips/syscalls/prctl.S
new file mode 100644
index 0000000..aaf1344
--- /dev/null
+++ b/libc/arch-mips/syscalls/prctl.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl prctl
+    .align 4
+    .ent prctl
+
+prctl:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_prctl
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end prctl
diff --git a/libc/arch-mips/syscalls/pread64.S b/libc/arch-mips/syscalls/pread64.S
new file mode 100644
index 0000000..86e817c
--- /dev/null
+++ b/libc/arch-mips/syscalls/pread64.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl pread64
+    .align 4
+    .ent pread64
+
+pread64:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_pread64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end pread64
diff --git a/libc/arch-mips/syscalls/pwrite64.S b/libc/arch-mips/syscalls/pwrite64.S
new file mode 100644
index 0000000..a8dcd98
--- /dev/null
+++ b/libc/arch-mips/syscalls/pwrite64.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl pwrite64
+    .align 4
+    .ent pwrite64
+
+pwrite64:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_pwrite64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end pwrite64
diff --git a/libc/arch-mips/syscalls/read.S b/libc/arch-mips/syscalls/read.S
new file mode 100644
index 0000000..75816cd
--- /dev/null
+++ b/libc/arch-mips/syscalls/read.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl read
+    .align 4
+    .ent read
+
+read:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_read
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end read
diff --git a/libc/arch-mips/syscalls/readahead.S b/libc/arch-mips/syscalls/readahead.S
new file mode 100644
index 0000000..5ec600d
--- /dev/null
+++ b/libc/arch-mips/syscalls/readahead.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl readahead
+    .align 4
+    .ent readahead
+
+readahead:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_readahead
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end readahead
diff --git a/libc/arch-mips/syscalls/readlink.S b/libc/arch-mips/syscalls/readlink.S
new file mode 100644
index 0000000..ccdd596
--- /dev/null
+++ b/libc/arch-mips/syscalls/readlink.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl readlink
+    .align 4
+    .ent readlink
+
+readlink:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_readlink
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end readlink
diff --git a/libc/arch-mips/syscalls/readv.S b/libc/arch-mips/syscalls/readv.S
new file mode 100644
index 0000000..0561c18
--- /dev/null
+++ b/libc/arch-mips/syscalls/readv.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl readv
+    .align 4
+    .ent readv
+
+readv:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_readv
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end readv
diff --git a/libc/arch-mips/syscalls/recvfrom.S b/libc/arch-mips/syscalls/recvfrom.S
new file mode 100644
index 0000000..cf3441d
--- /dev/null
+++ b/libc/arch-mips/syscalls/recvfrom.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl recvfrom
+    .align 4
+    .ent recvfrom
+
+recvfrom:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_recvfrom
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end recvfrom
diff --git a/libc/arch-mips/syscalls/recvmsg.S b/libc/arch-mips/syscalls/recvmsg.S
new file mode 100644
index 0000000..5f22c49
--- /dev/null
+++ b/libc/arch-mips/syscalls/recvmsg.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl recvmsg
+    .align 4
+    .ent recvmsg
+
+recvmsg:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_recvmsg
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end recvmsg
diff --git a/libc/arch-mips/syscalls/removexattr.S b/libc/arch-mips/syscalls/removexattr.S
new file mode 100644
index 0000000..7d12b96
--- /dev/null
+++ b/libc/arch-mips/syscalls/removexattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl removexattr
+    .align 4
+    .ent removexattr
+
+removexattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_removexattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end removexattr
diff --git a/libc/arch-mips/syscalls/rename.S b/libc/arch-mips/syscalls/rename.S
new file mode 100644
index 0000000..950d579
--- /dev/null
+++ b/libc/arch-mips/syscalls/rename.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl rename
+    .align 4
+    .ent rename
+
+rename:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_rename
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end rename
diff --git a/libc/arch-mips/syscalls/renameat.S b/libc/arch-mips/syscalls/renameat.S
new file mode 100644
index 0000000..a2f3c4f
--- /dev/null
+++ b/libc/arch-mips/syscalls/renameat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl renameat
+    .align 4
+    .ent renameat
+
+renameat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_renameat
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end renameat
diff --git a/libc/arch-mips/syscalls/rmdir.S b/libc/arch-mips/syscalls/rmdir.S
new file mode 100644
index 0000000..2f77d0d
--- /dev/null
+++ b/libc/arch-mips/syscalls/rmdir.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl rmdir
+    .align 4
+    .ent rmdir
+
+rmdir:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_rmdir
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end rmdir
diff --git a/libc/arch-mips/syscalls/sched_get_priority_max.S b/libc/arch-mips/syscalls/sched_get_priority_max.S
new file mode 100644
index 0000000..158b0fe
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_get_priority_max.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_get_priority_max
+    .align 4
+    .ent sched_get_priority_max
+
+sched_get_priority_max:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_get_priority_max
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_get_priority_max
diff --git a/libc/arch-mips/syscalls/sched_get_priority_min.S b/libc/arch-mips/syscalls/sched_get_priority_min.S
new file mode 100644
index 0000000..8c07d72
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_get_priority_min.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_get_priority_min
+    .align 4
+    .ent sched_get_priority_min
+
+sched_get_priority_min:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_get_priority_min
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_get_priority_min
diff --git a/libc/arch-mips/syscalls/sched_getparam.S b/libc/arch-mips/syscalls/sched_getparam.S
new file mode 100644
index 0000000..6aba7cf
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_getparam.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_getparam
+    .align 4
+    .ent sched_getparam
+
+sched_getparam:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_getparam
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_getparam
diff --git a/libc/arch-mips/syscalls/sched_getscheduler.S b/libc/arch-mips/syscalls/sched_getscheduler.S
new file mode 100644
index 0000000..33d7f49
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_getscheduler.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_getscheduler
+    .align 4
+    .ent sched_getscheduler
+
+sched_getscheduler:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_getscheduler
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_getscheduler
diff --git a/libc/arch-mips/syscalls/sched_rr_get_interval.S b/libc/arch-mips/syscalls/sched_rr_get_interval.S
new file mode 100644
index 0000000..e634ed0
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_rr_get_interval.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_rr_get_interval
+    .align 4
+    .ent sched_rr_get_interval
+
+sched_rr_get_interval:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_rr_get_interval
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_rr_get_interval
diff --git a/libc/arch-mips/syscalls/sched_setaffinity.S b/libc/arch-mips/syscalls/sched_setaffinity.S
new file mode 100644
index 0000000..aefc240
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_setaffinity.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_setaffinity
+    .align 4
+    .ent sched_setaffinity
+
+sched_setaffinity:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_setaffinity
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_setaffinity
diff --git a/libc/arch-mips/syscalls/sched_setparam.S b/libc/arch-mips/syscalls/sched_setparam.S
new file mode 100644
index 0000000..4d646bd
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_setparam.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_setparam
+    .align 4
+    .ent sched_setparam
+
+sched_setparam:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_setparam
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_setparam
diff --git a/libc/arch-mips/syscalls/sched_setscheduler.S b/libc/arch-mips/syscalls/sched_setscheduler.S
new file mode 100644
index 0000000..a79e39c
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_setscheduler.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_setscheduler
+    .align 4
+    .ent sched_setscheduler
+
+sched_setscheduler:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_setscheduler
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_setscheduler
diff --git a/libc/arch-mips/syscalls/sched_yield.S b/libc/arch-mips/syscalls/sched_yield.S
new file mode 100644
index 0000000..c7c99dc
--- /dev/null
+++ b/libc/arch-mips/syscalls/sched_yield.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sched_yield
+    .align 4
+    .ent sched_yield
+
+sched_yield:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sched_yield
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sched_yield
diff --git a/libc/arch-mips/syscalls/select.S b/libc/arch-mips/syscalls/select.S
new file mode 100644
index 0000000..ce4112f
--- /dev/null
+++ b/libc/arch-mips/syscalls/select.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl select
+    .align 4
+    .ent select
+
+select:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR__newselect
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end select
diff --git a/libc/arch-mips/syscalls/sendfile.S b/libc/arch-mips/syscalls/sendfile.S
new file mode 100644
index 0000000..c4c176e
--- /dev/null
+++ b/libc/arch-mips/syscalls/sendfile.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sendfile
+    .align 4
+    .ent sendfile
+
+sendfile:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sendfile
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sendfile
diff --git a/libc/arch-mips/syscalls/sendmsg.S b/libc/arch-mips/syscalls/sendmsg.S
new file mode 100644
index 0000000..1913f13
--- /dev/null
+++ b/libc/arch-mips/syscalls/sendmsg.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sendmsg
+    .align 4
+    .ent sendmsg
+
+sendmsg:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sendmsg
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sendmsg
diff --git a/libc/arch-mips/syscalls/sendto.S b/libc/arch-mips/syscalls/sendto.S
new file mode 100644
index 0000000..f17743d
--- /dev/null
+++ b/libc/arch-mips/syscalls/sendto.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sendto
+    .align 4
+    .ent sendto
+
+sendto:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sendto
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sendto
diff --git a/libc/arch-mips/syscalls/setgid.S b/libc/arch-mips/syscalls/setgid.S
new file mode 100644
index 0000000..83dbfe5
--- /dev/null
+++ b/libc/arch-mips/syscalls/setgid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setgid
+    .align 4
+    .ent setgid
+
+setgid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setgid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setgid
diff --git a/libc/arch-mips/syscalls/setgroups.S b/libc/arch-mips/syscalls/setgroups.S
new file mode 100644
index 0000000..ef9327d
--- /dev/null
+++ b/libc/arch-mips/syscalls/setgroups.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setgroups
+    .align 4
+    .ent setgroups
+
+setgroups:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setgroups
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setgroups
diff --git a/libc/arch-mips/syscalls/setitimer.S b/libc/arch-mips/syscalls/setitimer.S
new file mode 100644
index 0000000..b042e07
--- /dev/null
+++ b/libc/arch-mips/syscalls/setitimer.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setitimer
+    .align 4
+    .ent setitimer
+
+setitimer:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setitimer
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setitimer
diff --git a/libc/arch-mips/syscalls/setpgid.S b/libc/arch-mips/syscalls/setpgid.S
new file mode 100644
index 0000000..2ddc828
--- /dev/null
+++ b/libc/arch-mips/syscalls/setpgid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setpgid
+    .align 4
+    .ent setpgid
+
+setpgid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setpgid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setpgid
diff --git a/libc/arch-mips/syscalls/setpriority.S b/libc/arch-mips/syscalls/setpriority.S
new file mode 100644
index 0000000..02550e9
--- /dev/null
+++ b/libc/arch-mips/syscalls/setpriority.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setpriority
+    .align 4
+    .ent setpriority
+
+setpriority:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setpriority
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setpriority
diff --git a/libc/arch-mips/syscalls/setregid.S b/libc/arch-mips/syscalls/setregid.S
new file mode 100644
index 0000000..619b3a1
--- /dev/null
+++ b/libc/arch-mips/syscalls/setregid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setregid
+    .align 4
+    .ent setregid
+
+setregid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setregid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setregid
diff --git a/libc/arch-mips/syscalls/setresgid.S b/libc/arch-mips/syscalls/setresgid.S
new file mode 100644
index 0000000..3ff94c7
--- /dev/null
+++ b/libc/arch-mips/syscalls/setresgid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setresgid
+    .align 4
+    .ent setresgid
+
+setresgid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setresgid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setresgid
diff --git a/libc/arch-mips/syscalls/setrlimit.S b/libc/arch-mips/syscalls/setrlimit.S
new file mode 100644
index 0000000..3ec37c5
--- /dev/null
+++ b/libc/arch-mips/syscalls/setrlimit.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setrlimit
+    .align 4
+    .ent setrlimit
+
+setrlimit:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setrlimit
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setrlimit
diff --git a/libc/arch-mips/syscalls/setsid.S b/libc/arch-mips/syscalls/setsid.S
new file mode 100644
index 0000000..2a09663
--- /dev/null
+++ b/libc/arch-mips/syscalls/setsid.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setsid
+    .align 4
+    .ent setsid
+
+setsid:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setsid
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setsid
diff --git a/libc/arch-mips/syscalls/setsockopt.S b/libc/arch-mips/syscalls/setsockopt.S
new file mode 100644
index 0000000..dc5e62f
--- /dev/null
+++ b/libc/arch-mips/syscalls/setsockopt.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setsockopt
+    .align 4
+    .ent setsockopt
+
+setsockopt:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setsockopt
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setsockopt
diff --git a/libc/arch-mips/syscalls/settimeofday.S b/libc/arch-mips/syscalls/settimeofday.S
new file mode 100644
index 0000000..f7c03ea
--- /dev/null
+++ b/libc/arch-mips/syscalls/settimeofday.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl settimeofday
+    .align 4
+    .ent settimeofday
+
+settimeofday:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_settimeofday
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end settimeofday
diff --git a/libc/arch-mips/syscalls/setxattr.S b/libc/arch-mips/syscalls/setxattr.S
new file mode 100644
index 0000000..baa78a4
--- /dev/null
+++ b/libc/arch-mips/syscalls/setxattr.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl setxattr
+    .align 4
+    .ent setxattr
+
+setxattr:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_setxattr
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end setxattr
diff --git a/libc/arch-mips/syscalls/shutdown.S b/libc/arch-mips/syscalls/shutdown.S
new file mode 100644
index 0000000..b80d99b
--- /dev/null
+++ b/libc/arch-mips/syscalls/shutdown.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl shutdown
+    .align 4
+    .ent shutdown
+
+shutdown:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_shutdown
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end shutdown
diff --git a/libc/arch-mips/syscalls/sigaction.S b/libc/arch-mips/syscalls/sigaction.S
new file mode 100644
index 0000000..700da54
--- /dev/null
+++ b/libc/arch-mips/syscalls/sigaction.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sigaction
+    .align 4
+    .ent sigaction
+
+sigaction:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sigaction
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sigaction
diff --git a/libc/arch-mips/syscalls/sigaltstack.S b/libc/arch-mips/syscalls/sigaltstack.S
new file mode 100644
index 0000000..d2a4a9a
--- /dev/null
+++ b/libc/arch-mips/syscalls/sigaltstack.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sigaltstack
+    .align 4
+    .ent sigaltstack
+
+sigaltstack:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sigaltstack
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sigaltstack
diff --git a/libc/arch-mips/syscalls/sigpending.S b/libc/arch-mips/syscalls/sigpending.S
new file mode 100644
index 0000000..68df4db
--- /dev/null
+++ b/libc/arch-mips/syscalls/sigpending.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sigpending
+    .align 4
+    .ent sigpending
+
+sigpending:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sigpending
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sigpending
diff --git a/libc/arch-mips/syscalls/sigprocmask.S b/libc/arch-mips/syscalls/sigprocmask.S
new file mode 100644
index 0000000..17c01cb
--- /dev/null
+++ b/libc/arch-mips/syscalls/sigprocmask.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sigprocmask
+    .align 4
+    .ent sigprocmask
+
+sigprocmask:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sigprocmask
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sigprocmask
diff --git a/libc/arch-mips/syscalls/socket.S b/libc/arch-mips/syscalls/socket.S
new file mode 100644
index 0000000..e7d43f9
--- /dev/null
+++ b/libc/arch-mips/syscalls/socket.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl socket
+    .align 4
+    .ent socket
+
+socket:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_socket
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end socket
diff --git a/libc/arch-mips/syscalls/socketpair.S b/libc/arch-mips/syscalls/socketpair.S
new file mode 100644
index 0000000..97c67af
--- /dev/null
+++ b/libc/arch-mips/syscalls/socketpair.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl socketpair
+    .align 4
+    .ent socketpair
+
+socketpair:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_socketpair
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end socketpair
diff --git a/libc/arch-mips/syscalls/stat.S b/libc/arch-mips/syscalls/stat.S
new file mode 100644
index 0000000..aec910d
--- /dev/null
+++ b/libc/arch-mips/syscalls/stat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl stat
+    .align 4
+    .ent stat
+
+stat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_stat64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end stat
diff --git a/libc/arch-mips/syscalls/symlink.S b/libc/arch-mips/syscalls/symlink.S
new file mode 100644
index 0000000..f81c6dd
--- /dev/null
+++ b/libc/arch-mips/syscalls/symlink.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl symlink
+    .align 4
+    .ent symlink
+
+symlink:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_symlink
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end symlink
diff --git a/libc/arch-mips/syscalls/sync.S b/libc/arch-mips/syscalls/sync.S
new file mode 100644
index 0000000..a122873
--- /dev/null
+++ b/libc/arch-mips/syscalls/sync.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sync
+    .align 4
+    .ent sync
+
+sync:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sync
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sync
diff --git a/libc/arch-mips/syscalls/syscall.S b/libc/arch-mips/syscalls/syscall.S
new file mode 100644
index 0000000..2192bd5
--- /dev/null
+++ b/libc/arch-mips/syscalls/syscall.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl syscall
+    .align 4
+    .ent syscall
+
+syscall:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_syscall
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end syscall
diff --git a/libc/arch-mips/syscalls/sysinfo.S b/libc/arch-mips/syscalls/sysinfo.S
new file mode 100644
index 0000000..4577af9
--- /dev/null
+++ b/libc/arch-mips/syscalls/sysinfo.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl sysinfo
+    .align 4
+    .ent sysinfo
+
+sysinfo:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_sysinfo
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end sysinfo
diff --git a/libc/arch-mips/syscalls/tgkill.S b/libc/arch-mips/syscalls/tgkill.S
new file mode 100644
index 0000000..57b3a85
--- /dev/null
+++ b/libc/arch-mips/syscalls/tgkill.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl tgkill
+    .align 4
+    .ent tgkill
+
+tgkill:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_tgkill
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end tgkill
diff --git a/libc/arch-mips/syscalls/times.S b/libc/arch-mips/syscalls/times.S
new file mode 100644
index 0000000..3e8950d
--- /dev/null
+++ b/libc/arch-mips/syscalls/times.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl times
+    .align 4
+    .ent times
+
+times:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_times
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end times
diff --git a/libc/arch-mips/syscalls/tkill.S b/libc/arch-mips/syscalls/tkill.S
new file mode 100644
index 0000000..3037baa
--- /dev/null
+++ b/libc/arch-mips/syscalls/tkill.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl tkill
+    .align 4
+    .ent tkill
+
+tkill:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_tkill
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end tkill
diff --git a/libc/arch-mips/syscalls/truncate.S b/libc/arch-mips/syscalls/truncate.S
new file mode 100644
index 0000000..4a8f12c
--- /dev/null
+++ b/libc/arch-mips/syscalls/truncate.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl truncate
+    .align 4
+    .ent truncate
+
+truncate:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_truncate
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end truncate
diff --git a/libc/arch-mips/syscalls/umask.S b/libc/arch-mips/syscalls/umask.S
new file mode 100644
index 0000000..eee911e
--- /dev/null
+++ b/libc/arch-mips/syscalls/umask.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl umask
+    .align 4
+    .ent umask
+
+umask:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_umask
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end umask
diff --git a/libc/arch-mips/syscalls/umount2.S b/libc/arch-mips/syscalls/umount2.S
new file mode 100644
index 0000000..c6d9df6
--- /dev/null
+++ b/libc/arch-mips/syscalls/umount2.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl umount2
+    .align 4
+    .ent umount2
+
+umount2:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_umount2
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end umount2
diff --git a/libc/arch-mips/syscalls/uname.S b/libc/arch-mips/syscalls/uname.S
new file mode 100644
index 0000000..7e4f780
--- /dev/null
+++ b/libc/arch-mips/syscalls/uname.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl uname
+    .align 4
+    .ent uname
+
+uname:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_uname
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end uname
diff --git a/libc/arch-mips/syscalls/unlink.S b/libc/arch-mips/syscalls/unlink.S
new file mode 100644
index 0000000..fd8dad9
--- /dev/null
+++ b/libc/arch-mips/syscalls/unlink.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl unlink
+    .align 4
+    .ent unlink
+
+unlink:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_unlink
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end unlink
diff --git a/libc/arch-mips/syscalls/unlinkat.S b/libc/arch-mips/syscalls/unlinkat.S
new file mode 100644
index 0000000..793ab5e
--- /dev/null
+++ b/libc/arch-mips/syscalls/unlinkat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl unlinkat
+    .align 4
+    .ent unlinkat
+
+unlinkat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_unlinkat
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end unlinkat
diff --git a/libc/arch-mips/syscalls/utimensat.S b/libc/arch-mips/syscalls/utimensat.S
new file mode 100644
index 0000000..435c49e
--- /dev/null
+++ b/libc/arch-mips/syscalls/utimensat.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl utimensat
+    .align 4
+    .ent utimensat
+
+utimensat:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_utimensat
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end utimensat
diff --git a/libc/arch-mips/syscalls/utimes.S b/libc/arch-mips/syscalls/utimes.S
new file mode 100644
index 0000000..8ce1e44
--- /dev/null
+++ b/libc/arch-mips/syscalls/utimes.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl utimes
+    .align 4
+    .ent utimes
+
+utimes:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_utimes
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end utimes
diff --git a/libc/arch-mips/syscalls/write.S b/libc/arch-mips/syscalls/write.S
new file mode 100644
index 0000000..a772ace
--- /dev/null
+++ b/libc/arch-mips/syscalls/write.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl write
+    .align 4
+    .ent write
+
+write:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_write
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end write
diff --git a/libc/arch-mips/syscalls/writev.S b/libc/arch-mips/syscalls/writev.S
new file mode 100644
index 0000000..bdacb42
--- /dev/null
+++ b/libc/arch-mips/syscalls/writev.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl writev
+    .align 4
+    .ent writev
+
+writev:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_writev
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end writev
diff --git a/libc/arch-sh/syscalls/personality.S b/libc/arch-sh/syscalls/personality.S
deleted file mode 100644
index efc2ea3..0000000
--- a/libc/arch-sh/syscalls/personality.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/* autogenerated by gensyscalls.py */
-#include <sys/linux-syscalls.h>
-
-    .text
-    .type personality, @function
-    .globl personality
-    .align 4
-
-personality:
-
-    /* invoke trap */
-    mov.l   0f, r3  /* trap num */
-    trapa   #(1 + 0x10)
-
-    /* check return value */
-    cmp/pz  r0
-    bt      __NR_personality_end
-
-    /* keep error number */
-    sts.l   pr, @-r15
-    mov.l   1f, r1
-    jsr     @r1
-    mov     r0, r4
-    lds.l   @r15+, pr
-
-__NR_personality_end:
-    rts
-    nop
-
-    .align  2
-0:  .long   __NR_personality
-1:  .long   __set_syscall_errno
diff --git a/libc/private/__dso_handle.S b/libc/arch-x86/bionic/__dso_handle.S
similarity index 100%
rename from libc/private/__dso_handle.S
rename to libc/arch-x86/bionic/__dso_handle.S
diff --git a/libc/private/__dso_handle_so.S b/libc/arch-x86/bionic/__dso_handle_so.S
similarity index 100%
rename from libc/private/__dso_handle_so.S
rename to libc/arch-x86/bionic/__dso_handle_so.S
diff --git a/libc/arch-x86/bionic/crtbegin_dynamic.S b/libc/arch-x86/bionic/crtbegin.S
similarity index 97%
rename from libc/arch-x86/bionic/crtbegin_dynamic.S
rename to libc/arch-x86/bionic/crtbegin.S
index 177244b..39b6af0 100644
--- a/libc/arch-x86/bionic/crtbegin_dynamic.S
+++ b/libc/arch-x86/bionic/crtbegin.S
@@ -30,8 +30,7 @@
 	.globl _start
 
 # this is the small startup code that is first run when
-# any executable that is dynamically-linked with Bionic
-# runs.
+# any executable that is linked with Bionic runs.
 #
 # it's purpose is to call __libc_init with appropriate
 # arguments, which are:
diff --git a/libc/arch-x86/bionic/crtbegin_static.S b/libc/arch-x86/bionic/crtbegin_static.S
deleted file mode 100644
index 4fffecd..0000000
--- a/libc/arch-x86/bionic/crtbegin_static.S
+++ /dev/null
@@ -1,138 +0,0 @@
-# bionic/arch-x86/bionic/crtbegin_static.S
-#
-# Copyright 2006, The Android Open Source Project
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in the
-#       documentation and/or other materials provided with the distribution.
-#     * Neither the name of Google Inc. nor the names of its contributors may
-#       be used to endorse or promote products derived from this software
-#       without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 
-# EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
-# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
-# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
-# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-	.text
-	.align 4
-	.type _start, @function
-	.globl _start
-
-# this is the small startup code that is first run when
-# any executable that is statically-linked with Bionic
-# runs.
-#
-# it's purpose is to call __libc_init with appropriate
-# arguments, which are:
-#
-#    - the address of the raw data block setup by the Linux
-#      kernel ELF loader
-#
-#    - address of an "onexit" function, not used on any
-#      platform supported by Bionic
-#
-#    - address of the "main" function of the program. We
-#      can't hard-code it in the adr pseudo instruction
-#      so we use a tiny trampoline that will get relocated
-#      by the dynamic linker before this code runs
-#
-#    - address of the constructor list
-#
-_start:	
-        mov     %esp, %eax
-        # before push arguments, align the stack to a 16 byte boundary
-        andl    $~15, %esp
-        mov     $1f, %edx
-        pushl   %edx
-        mov     $0f, %edx
-        pushl   %edx
-        mov     $0, %edx
-        pushl   %edx
-        pushl   %eax
-        call    __libc_init
-
-0:  jmp   main
-
-1:  .long   __PREINIT_ARRAY__
-    .long   __INIT_ARRAY__
-    .long   __FINI_ARRAY__
-
-	.section .preinit_array, "aw"
-	.globl __PREINIT_ARRAY__
-__PREINIT_ARRAY__:
-	.long -1
-
-	.section .init_array, "aw"
-	.globl __INIT_ARRAY__
-__INIT_ARRAY__:
-	.long -1
-	.long	frame_dummy
-
-	.section .fini_array, "aw"
-	.globl __FINI_ARRAY__
-__FINI_ARRAY__:
-	.long -1
-	.long	__do_global_dtors_aux
-
-	.section	.eh_frame,"a",@progbits
-	.align 4
-	.type	__EH_FRAME_BEGIN__, @object
-__EH_FRAME_BEGIN__:
-	.text
-	.p2align 4,,15
-	.type	__do_global_dtors_aux, @function
-__do_global_dtors_aux:
-	pushl	%ebp
-	movl	%esp, %ebp
-	subl	$24, %esp
-	cmpb	$0, completed.4454
-	jne	.L4
-	movl	$__deregister_frame_info_bases, %eax
-	testl	%eax, %eax
-	je	.L3
-	movl	$__EH_FRAME_BEGIN__, (%esp)
-	call	__deregister_frame_info_bases
-.L3:
-	movb	$1, completed.4454
-.L4:
-	leave
-	ret
-	.text
-	.p2align 4,,15
-	.type	frame_dummy, @function
-frame_dummy:
-	pushl	%ebp
-	movl	$__register_frame_info_bases, %eax
-	movl	%esp, %ebp
-	subl	$24, %esp
-	testl	%eax, %eax
-	je	.L7
-	movl	%ebx, 12(%esp)
-	movl	$0, 8(%esp)
-	movl	$object.4466, 4(%esp)
-	movl	$__EH_FRAME_BEGIN__, (%esp)
-	call	__register_frame_info_bases
-.L7:
-	leave
-	ret
-	.local	completed.4454
-	.comm	completed.4454,1,1
-	.local	object.4466
-	.comm	object.4466,24,4
-	.weak	__register_frame_info_bases
-	.weak	__deregister_frame_info_bases
-
-#include "__dso_handle.S"
-#include "atexit.S"
-#include "__stack_chk_fail_local.S"
diff --git a/libc/arch-x86/string/ssse3-memcpy5.S b/libc/arch-x86/string/ssse3-memcpy5.S
index 1bf6d22..b0612a6 100644
--- a/libc/arch-x86/string/ssse3-memcpy5.S
+++ b/libc/arch-x86/string/ssse3-memcpy5.S
@@ -29,23 +29,19 @@
 */
 
 #ifndef MEMCPY
-# define MEMCPY         ssse3_memcpy5
+# define MEMCPY	ssse3_memcpy5
 #endif
 
 #ifndef L
 # define L(label)	.L##label
 #endif
 
-#ifndef ALIGN
-# define ALIGN(n)	.p2align n
-#endif
-
 #ifndef cfi_startproc
-# define cfi_startproc			.cfi_startproc
+# define cfi_startproc	.cfi_startproc
 #endif
 
 #ifndef cfi_endproc
-# define cfi_endproc			.cfi_endproc
+# define cfi_endproc	.cfi_endproc
 #endif
 
 #ifndef cfi_rel_offset
@@ -53,33 +49,25 @@
 #endif
 
 #ifndef cfi_restore
-# define cfi_restore(reg)		.cfi_restore reg
+# define cfi_restore(reg)	.cfi_restore reg
 #endif
 
 #ifndef cfi_adjust_cfa_offset
 # define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
 #endif
 
-#ifndef cfi_remember_state
-# define cfi_remember_state		.cfi_remember_state
-#endif
-
-#ifndef cfi_restore_state
-# define cfi_restore_state		.cfi_restore_state
-#endif
-
 #ifndef ENTRY
-# define ENTRY(name)			\
-	.type name,  @function; 	\
-	.globl name;			\
-	.p2align 4;			\
-name:					\
+# define ENTRY(name)		\
+	.type name,  @function;		\
+	.globl name;		\
+	.p2align 4;		\
+name:		\
 	cfi_startproc
 #endif
 
 #ifndef END
-# define END(name)			\
-	cfi_endproc;			\
+# define END(name)		\
+	cfi_endproc;		\
 	.size name, .-name
 #endif
 
@@ -93,12 +81,12 @@
 # define LEN		SRC+4
 #endif
 
-#define CFI_PUSH(REG)						\
-  cfi_adjust_cfa_offset (4);					\
+#define CFI_PUSH(REG)		\
+  cfi_adjust_cfa_offset (4);		\
   cfi_rel_offset (REG, 0)
 
-#define CFI_POP(REG)						\
-  cfi_adjust_cfa_offset (-4);					\
+#define CFI_POP(REG)		\
+  cfi_adjust_cfa_offset (-4);		\
   cfi_restore (REG)
 
 #define PUSH(REG)	pushl REG; CFI_PUSH (REG)
@@ -110,38 +98,26 @@
 # define RETURN_END	POP (%ebx); ret
 # define RETURN		RETURN_END; CFI_PUSH (%ebx)
 # define JMPTBL(I, B)	I - B
+# undef __i686
+
+# define SETUP_PIC_REG(x)	call	__i686.get_pc_thunk.x
 
 /* Load an entry in a jump table into EBX and branch to it.  TABLE is a
-   jump table with relative offsets.  INDEX is a register contains the
-   index into the jump table.   SCALE is the scale of INDEX. */
+	jump table with relative offsets.  INDEX is a register contains the
+	index into the jump table.   SCALE is the scale of INDEX. */
+
 # define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE)		\
-    /* We first load PC into EBX.  */				\
-    call	__i686.get_pc_thunk.bx;				\
-    /* Get the address of the jump table.  */			\
-    addl	$(TABLE - .), %ebx;				\
-    /* Get the entry and convert the relative offset to the	\
-       absolute address.  */					\
-    addl	(%ebx,INDEX,SCALE), %ebx;			\
-    /* We loaded the jump table.  Go.  */			\
-    jmp		*%ebx
-
-# define BRANCH_TO_JMPTBL_ENTRY_VALUE(TABLE)			\
-    addl	$(TABLE - .), %ebx
-
-# define BRANCH_TO_JMPTBL_ENTRY_TAIL(TABLE, INDEX, SCALE)	\
-    addl	(%ebx,INDEX,SCALE), %ebx;			\
-    /* We loaded the jump table.  Go.  */			\
-    jmp		*%ebx
-
-	.section	.gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
-	.globl	__i686.get_pc_thunk.bx
-	.hidden	__i686.get_pc_thunk.bx
-	ALIGN (4)
-	.type	__i686.get_pc_thunk.bx,@function
-__i686.get_pc_thunk.bx:
-	movl	(%esp), %ebx
-	ret
+    /* We first load PC into EBX.  */		\
+	SETUP_PIC_REG(bx);		\
+    /* Get the address of the jump table.  */		\
+	addl	$(TABLE - .), %ebx;		\
+    /* Get the entry and convert the relative offset to the		\
+	absolute	address.  */		\
+	addl	(%ebx, INDEX, SCALE), %ebx;		\
+    /* We loaded the jump table.  Go.  */		\
+	jmp	*%ebx
 #else
+
 # define PARMS		4
 # define ENTRANCE
 # define RETURN_END	ret
@@ -149,15 +125,11 @@
 # define JMPTBL(I, B)	I
 
 /* Branch to an entry in a jump table.  TABLE is a jump table with
-   absolute offsets.  INDEX is a register contains the index into the
-   jump table.  SCALE is the scale of INDEX. */
+	absolute offsets.  INDEX is a register contains the index into the
+	jump table.  SCALE is the scale of INDEX. */
+
 # define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE)		\
-    jmp		*TABLE(,INDEX,SCALE)
-
-# define BRANCH_TO_JMPTBL_ENTRY_VALUE(TABLE)
-
-# define BRANCH_TO_JMPTBL_ENTRY_TAIL(TABLE, INDEX, SCALE)		\
-    jmp		*TABLE(,INDEX,SCALE)
+	jmp	*TABLE(, INDEX, SCALE)
 #endif
 
 	.section .text.ssse3,"ax",@progbits
@@ -174,6 +146,8 @@
 	cmp	$32, %ecx
 	jae	L(memmove_bwd)
 	jmp	L(bk_write_less32bytes_2)
+
+	.p2align 4
 L(memmove_bwd):
 	add	%ecx, %eax
 	cmp	%eax, %edx
@@ -194,21 +168,25 @@
 	add	%ecx, %eax
 	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd), %ecx, 4)
 #ifndef USE_AS_MEMMOVE
+	.p2align 4
 L(bk_write):
 	BRANCH_TO_JMPTBL_ENTRY (L(table_48_bytes_bwd), %ecx, 4)
 #endif
 
-	ALIGN (4)
-/* ECX > 32 and EDX is 4 byte aligned.  */
+	.p2align 4
 L(48bytesormore):
+#ifndef USE_AS_MEMMOVE
+	movlpd	(%eax), %xmm0
+	movlpd	8(%eax), %xmm1
+	movlpd	%xmm0, (%edx)
+	movlpd	%xmm1, 8(%edx)
+#else
 	movdqu	(%eax), %xmm0
+#endif
 	PUSH (%edi)
 	movl	%edx, %edi
 	and	$-16, %edx
-	PUSH (%esi)
-	cfi_remember_state
 	add	$16, %edx
-	movl	%edi, %esi
 	sub	%edx, %edi
 	add	%edi, %ecx
 	sub	%edi, %eax
@@ -217,7 +195,7 @@
 	cmp	$SHARED_CACHE_SIZE_HALF, %ecx
 #else
 # if (defined SHARED || defined __PIC__)
-	call	__i686.get_pc_thunk.bx
+	SETUP_PIC_REG(bx)
 	add	$_GLOBAL_OFFSET_TABLE_, %ebx
 	cmp	__x86_shared_cache_size_half@GOTOFF(%ebx), %ecx
 # else
@@ -229,19 +207,20 @@
 	jae	L(large_page)
 	and	$0xf, %edi
 	jz	L(shl_0)
-
 	BRANCH_TO_JMPTBL_ENTRY (L(shl_table), %edi, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	.p2align 4
 L(shl_0):
-	movdqu	%xmm0, (%esi)
+#ifdef USE_AS_MEMMOVE
+	movl	DEST+4(%esp), %edi
+	movdqu	%xmm0, (%edi)
+#endif
 	xor	%edi, %edi
-	POP (%esi)
 	cmp	$127, %ecx
 	ja	L(shl_0_gobble)
 	lea	-32(%ecx), %ecx
+
+	.p2align 4
 L(shl_0_loop):
 	movdqa	(%eax, %edi), %xmm0
 	movdqa	16(%eax, %edi), %xmm1
@@ -273,32 +252,35 @@
 	movdqa	%xmm0, (%edx, %edi)
 	movdqa	%xmm1, 16(%edx, %edi)
 	lea	32(%edi), %edi
+
 L(shl_0_end):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	add	%edi, %eax
 	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd), %ecx, 4)
+	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd_align), %ecx, 4)
 
 	CFI_PUSH (%edi)
-L(shl_0_gobble):
 
+	.p2align 4
+L(shl_0_gobble):
 #ifdef DATA_CACHE_SIZE_HALF
 	cmp	$DATA_CACHE_SIZE_HALF, %ecx
 #else
 # if (defined SHARED || defined __PIC__)
-	call	__i686.get_pc_thunk.bx
+	SETUP_PIC_REG(bx)
 	add	$_GLOBAL_OFFSET_TABLE_, %ebx
 	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
 # else
 	cmp	__x86_data_cache_size_half, %ecx
 # endif
 #endif
-
-	POP (%edi)
+	POP	(%edi)
 	lea	-128(%ecx), %ecx
 	jae	L(shl_0_gobble_mem_loop)
+
+	.p2align 4
 L(shl_0_gobble_cache_loop):
 	movdqa	(%eax), %xmm0
 	movdqa	0x10(%eax), %xmm1
@@ -328,17 +310,15 @@
 	movdqa	(%eax), %xmm0
 	sub	$0x40, %ecx
 	movdqa	0x10(%eax), %xmm1
-
 	movdqa	%xmm0, (%edx)
 	movdqa	%xmm1, 0x10(%edx)
-
 	movdqa	0x20(%eax), %xmm0
 	movdqa	0x30(%eax), %xmm1
 	add	$0x40, %eax
-
 	movdqa	%xmm0, 0x20(%edx)
 	movdqa	%xmm1, 0x30(%edx)
 	add	$0x40, %edx
+
 L(shl_0_cache_less_64bytes):
 	cmp	$0x20, %ecx
 	jb	L(shl_0_cache_less_32bytes)
@@ -349,6 +329,7 @@
 	movdqa	%xmm0, (%edx)
 	movdqa	%xmm1, 0x10(%edx)
 	add	$0x20, %edx
+
 L(shl_0_cache_less_32bytes):
 	cmp	$0x10, %ecx
 	jb	L(shl_0_cache_less_16bytes)
@@ -357,13 +338,13 @@
 	add	$0x10, %eax
 	movdqa	%xmm0, (%edx)
 	add	$0x10, %edx
+
 L(shl_0_cache_less_16bytes):
 	add	%ecx, %edx
 	add	%ecx, %eax
 	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd), %ecx, 4)
 
-
-	ALIGN (4)
+	.p2align 4
 L(shl_0_gobble_mem_loop):
 	prefetcht0 0x1c0(%eax)
 	prefetcht0 0x280(%eax)
@@ -408,6 +389,7 @@
 	movdqa	%xmm0, 0x20(%edx)
 	movdqa	%xmm1, 0x30(%edx)
 	add	$0x40, %edx
+
 L(shl_0_mem_less_64bytes):
 	cmp	$0x20, %ecx
 	jb	L(shl_0_mem_less_32bytes)
@@ -418,6 +400,7 @@
 	movdqa	%xmm0, (%edx)
 	movdqa	%xmm1, 0x10(%edx)
 	add	$0x20, %edx
+
 L(shl_0_mem_less_32bytes):
 	cmp	$0x10, %ecx
 	jb	L(shl_0_mem_less_16bytes)
@@ -426,24 +409,84 @@
 	add	$0x10, %eax
 	movdqa	%xmm0, (%edx)
 	add	$0x10, %edx
+
 L(shl_0_mem_less_16bytes):
 	add	%ecx, %edx
 	add	%ecx, %eax
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd), %ecx, 4)
+	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd_align), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	.p2align 4
 L(shl_1):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-1(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_1_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-1(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-1(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_1_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl1LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	15(%eax), %xmm2
+	movaps	31(%eax), %xmm3
+	movaps	47(%eax), %xmm4
+	movaps	63(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$1, %xmm4, %xmm5
+	palignr	$1, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$1, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$1, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl1LoopStart)
+
+L(Shl1LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	15(%eax), %xmm2
+	movaps	31(%eax), %xmm3
+	palignr	$1, %xmm2, %xmm3
+	palignr	$1, %xmm1, %xmm2
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_1_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-1(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_1_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -453,8 +496,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_1_end)
+	jb	L(sh_1_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -465,30 +507,90 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_1_no_prefetch_loop)
 
-	jae	L(shl_1_loop)
-
-L(shl_1_end):
+L(sh_1_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	1(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_2):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-2(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_2_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-2(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-2(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_2_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl2LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	14(%eax), %xmm2
+	movaps	30(%eax), %xmm3
+	movaps	46(%eax), %xmm4
+	movaps	62(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$2, %xmm4, %xmm5
+	palignr	$2, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$2, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$2, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl2LoopStart)
+
+L(Shl2LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	14(%eax), %xmm2
+	movaps	30(%eax), %xmm3
+	palignr	$2, %xmm2, %xmm3
+	palignr	$2, %xmm1, %xmm2
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_2_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-2(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_2_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -498,8 +600,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_2_end)
+	jb	L(sh_2_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -510,30 +611,90 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_2_no_prefetch_loop)
 
-	jae	L(shl_2_loop)
-
-L(shl_2_end):
+L(sh_2_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	2(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_3):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-3(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_3_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-3(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-3(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_3_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl3LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	13(%eax), %xmm2
+	movaps	29(%eax), %xmm3
+	movaps	45(%eax), %xmm4
+	movaps	61(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$3, %xmm4, %xmm5
+	palignr	$3, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$3, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$3, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl3LoopStart)
+
+L(Shl3LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	13(%eax), %xmm2
+	movaps	29(%eax), %xmm3
+	palignr	$3, %xmm2, %xmm3
+	palignr	$3, %xmm1, %xmm2
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_3_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-3(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_3_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -544,7 +705,7 @@
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
 
-	jb	L(shl_3_end)
+	jb	L(sh_3_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -556,29 +717,90 @@
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
 
-	jae	L(shl_3_loop)
+	jae	L(sh_3_no_prefetch_loop)
 
-L(shl_3_end):
+L(sh_3_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	3(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_4):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-4(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_4_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-4(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-4(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_4_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl4LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	12(%eax), %xmm2
+	movaps	28(%eax), %xmm3
+	movaps	44(%eax), %xmm4
+	movaps	60(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$4, %xmm4, %xmm5
+	palignr	$4, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$4, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$4, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl4LoopStart)
+
+L(Shl4LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	12(%eax), %xmm2
+	movaps	28(%eax), %xmm3
+	palignr	$4, %xmm2, %xmm3
+	palignr	$4, %xmm1, %xmm2
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_4_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-4(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_4_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -589,7 +811,7 @@
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
 
-	jb	L(shl_4_end)
+	jb	L(sh_4_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -601,29 +823,90 @@
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
 
-	jae	L(shl_4_loop)
+	jae	L(sh_4_no_prefetch_loop)
 
-L(shl_4_end):
+L(sh_4_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	4(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_5):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-5(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_5_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-5(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-5(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_5_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl5LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	11(%eax), %xmm2
+	movaps	27(%eax), %xmm3
+	movaps	43(%eax), %xmm4
+	movaps	59(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$5, %xmm4, %xmm5
+	palignr	$5, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$5, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$5, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl5LoopStart)
+
+L(Shl5LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	11(%eax), %xmm2
+	movaps	27(%eax), %xmm3
+	palignr	$5, %xmm2, %xmm3
+	palignr	$5, %xmm1, %xmm2
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_5_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-5(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_5_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -634,7 +917,7 @@
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
 
-	jb	L(shl_5_end)
+	jb	L(sh_5_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -646,29 +929,90 @@
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
 
-	jae	L(shl_5_loop)
+	jae	L(sh_5_no_prefetch_loop)
 
-L(shl_5_end):
+L(sh_5_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	5(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_6):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-6(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_6_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-6(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-6(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_6_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl6LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	10(%eax), %xmm2
+	movaps	26(%eax), %xmm3
+	movaps	42(%eax), %xmm4
+	movaps	58(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$6, %xmm4, %xmm5
+	palignr	$6, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$6, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$6, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl6LoopStart)
+
+L(Shl6LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	10(%eax), %xmm2
+	movaps	26(%eax), %xmm3
+	palignr	$6, %xmm2, %xmm3
+	palignr	$6, %xmm1, %xmm2
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_6_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-6(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_6_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -679,7 +1023,7 @@
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
 
-	jb	L(shl_6_end)
+	jb	L(sh_6_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -691,29 +1035,90 @@
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
 
-	jae	L(shl_6_loop)
+	jae	L(sh_6_no_prefetch_loop)
 
-L(shl_6_end):
+L(sh_6_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	6(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_7):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-7(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_7_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-7(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-7(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_7_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl7LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	9(%eax), %xmm2
+	movaps	25(%eax), %xmm3
+	movaps	41(%eax), %xmm4
+	movaps	57(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$7, %xmm4, %xmm5
+	palignr	$7, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$7, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$7, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl7LoopStart)
+
+L(Shl7LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	9(%eax), %xmm2
+	movaps	25(%eax), %xmm3
+	palignr	$7, %xmm2, %xmm3
+	palignr	$7, %xmm1, %xmm2
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_7_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-7(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_7_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -723,8 +1128,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_7_end)
+	jb	L(sh_7_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -735,30 +1139,90 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_7_no_prefetch_loop)
 
-	jae	L(shl_7_loop)
-
-L(shl_7_end):
+L(sh_7_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	7(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_8):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-8(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_8_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-8(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-8(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_8_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl8LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	8(%eax), %xmm2
+	movaps	24(%eax), %xmm3
+	movaps	40(%eax), %xmm4
+	movaps	56(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$8, %xmm4, %xmm5
+	palignr	$8, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$8, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$8, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl8LoopStart)
+
+L(LoopLeave8):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	8(%eax), %xmm2
+	movaps	24(%eax), %xmm3
+	palignr	$8, %xmm2, %xmm3
+	palignr	$8, %xmm1, %xmm2
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_8_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-8(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_8_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -768,8 +1232,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_8_end)
+	jb	L(sh_8_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -780,30 +1243,91 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_8_no_prefetch_loop)
 
-	jae	L(shl_8_loop)
-
-L(shl_8_end):
+L(sh_8_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	8(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_9):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-9(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_9_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-9(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-9(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_9_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl9LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	7(%eax), %xmm2
+	movaps	23(%eax), %xmm3
+	movaps	39(%eax), %xmm4
+	movaps	55(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$9, %xmm4, %xmm5
+	palignr	$9, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$9, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$9, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl9LoopStart)
+
+L(Shl9LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	7(%eax), %xmm2
+	movaps	23(%eax), %xmm3
+	palignr	$9, %xmm2, %xmm3
+	palignr	$9, %xmm1, %xmm2
+
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_9_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-9(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_9_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -813,8 +1337,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_9_end)
+	jb	L(sh_9_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -825,30 +1348,91 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_9_no_prefetch_loop)
 
-	jae	L(shl_9_loop)
-
-L(shl_9_end):
+L(sh_9_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	9(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_10):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-10(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_10_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-10(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-10(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_10_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl10LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	6(%eax), %xmm2
+	movaps	22(%eax), %xmm3
+	movaps	38(%eax), %xmm4
+	movaps	54(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$10, %xmm4, %xmm5
+	palignr	$10, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$10, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$10, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl10LoopStart)
+
+L(Shl10LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	6(%eax), %xmm2
+	movaps	22(%eax), %xmm3
+	palignr	$10, %xmm2, %xmm3
+	palignr	$10, %xmm1, %xmm2
+
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_10_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-10(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_10_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -858,8 +1442,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_10_end)
+	jb	L(sh_10_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -870,30 +1453,91 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_10_no_prefetch_loop)
 
-	jae	L(shl_10_loop)
-
-L(shl_10_end):
+L(sh_10_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	10(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_11):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-11(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_11_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-11(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-11(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_11_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl11LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	5(%eax), %xmm2
+	movaps	21(%eax), %xmm3
+	movaps	37(%eax), %xmm4
+	movaps	53(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$11, %xmm4, %xmm5
+	palignr	$11, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$11, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$11, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl11LoopStart)
+
+L(Shl11LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	5(%eax), %xmm2
+	movaps	21(%eax), %xmm3
+	palignr	$11, %xmm2, %xmm3
+	palignr	$11, %xmm1, %xmm2
+
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_11_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-11(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_11_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -903,8 +1547,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_11_end)
+	jb	L(sh_11_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -915,30 +1558,91 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_11_no_prefetch_loop)
 
-	jae	L(shl_11_loop)
-
-L(shl_11_end):
+L(sh_11_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	11(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_12):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-12(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_12_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-12(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-12(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_12_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl12LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	4(%eax), %xmm2
+	movaps	20(%eax), %xmm3
+	movaps	36(%eax), %xmm4
+	movaps	52(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$12, %xmm4, %xmm5
+	palignr	$12, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$12, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$12, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl12LoopStart)
+
+L(Shl12LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	4(%eax), %xmm2
+	movaps	20(%eax), %xmm3
+	palignr	$12, %xmm2, %xmm3
+	palignr	$12, %xmm1, %xmm2
+
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_12_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-12(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_12_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -948,8 +1652,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_12_end)
+	jb	L(sh_12_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -960,30 +1663,91 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_12_no_prefetch_loop)
 
-	jae	L(shl_12_loop)
-
-L(shl_12_end):
+L(sh_12_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	12(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_13):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-13(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_13_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-13(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-13(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_13_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl13LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	3(%eax), %xmm2
+	movaps	19(%eax), %xmm3
+	movaps	35(%eax), %xmm4
+	movaps	51(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$13, %xmm4, %xmm5
+	palignr	$13, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$13, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$13, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl13LoopStart)
+
+L(Shl13LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	3(%eax), %xmm2
+	movaps	19(%eax), %xmm3
+	palignr	$13, %xmm2, %xmm3
+	palignr	$13, %xmm1, %xmm2
+
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_13_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-13(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_13_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -993,8 +1757,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_13_end)
+	jb	L(sh_13_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -1005,30 +1768,91 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_13_no_prefetch_loop)
 
-	jae	L(shl_13_loop)
-
-L(shl_13_end):
+L(sh_13_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	13(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_14):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-14(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_14_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-14(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-14(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_14_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl14LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	2(%eax), %xmm2
+	movaps	18(%eax), %xmm3
+	movaps	34(%eax), %xmm4
+	movaps	50(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$14, %xmm4, %xmm5
+	palignr	$14, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$14, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$14, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl14LoopStart)
+
+L(Shl14LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	2(%eax), %xmm2
+	movaps	18(%eax), %xmm3
+	palignr	$14, %xmm2, %xmm3
+	palignr	$14, %xmm1, %xmm2
+
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_14_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-14(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_14_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -1038,8 +1862,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_14_end)
+	jb	L(sh_14_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -1050,30 +1873,91 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_14_no_prefetch_loop)
 
-	jae	L(shl_14_loop)
-
-L(shl_14_end):
+L(sh_14_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	14(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(shl_15):
-	BRANCH_TO_JMPTBL_ENTRY_VALUE(L(table_48bytes_fwd))
-	lea	-15(%eax), %eax
-	movaps	(%eax), %xmm1
-	xor	%edi, %edi
-	lea	-32(%ecx), %ecx
-	movdqu	%xmm0, (%esi)
-	POP (%esi)
-L(shl_15_loop):
+#ifndef USE_AS_MEMMOVE
+	movaps	-15(%eax), %xmm1
+#else
+	movl	DEST+4(%esp), %edi
+	movaps	-15(%eax), %xmm1
+	movdqu	%xmm0, (%edi)
+#endif
+#ifdef DATA_CACHE_SIZE_HALF
+	cmp	$DATA_CACHE_SIZE_HALF, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+	SETUP_PIC_REG(bx)
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
+# else
+	cmp	__x86_data_cache_size_half, %ecx
+# endif
+#endif
+	jb L(sh_15_no_prefetch)
 
+	lea	-64(%ecx), %ecx
+
+	.p2align 4
+L(Shl15LoopStart):
+	prefetcht0 0x1c0(%eax)
+	prefetcht0 0x1c0(%edx)
+	movaps	1(%eax), %xmm2
+	movaps	17(%eax), %xmm3
+	movaps	33(%eax), %xmm4
+	movaps	49(%eax), %xmm5
+	movaps	%xmm5, %xmm7
+	palignr	$15, %xmm4, %xmm5
+	palignr	$15, %xmm3, %xmm4
+	movaps	%xmm5, 48(%edx)
+	palignr	$15, %xmm2, %xmm3
+	lea	64(%eax), %eax
+	palignr	$15, %xmm1, %xmm2
+	movaps	%xmm4, 32(%edx)
+	movaps	%xmm3, 16(%edx)
+	movaps	%xmm7, %xmm1
+	movaps	%xmm2, (%edx)
+	lea	64(%edx), %edx
+	sub	$64, %ecx
+	ja	L(Shl15LoopStart)
+
+L(Shl15LoopLeave):
+	add	$32, %ecx
+	jle	L(shl_end_0)
+
+	movaps	1(%eax), %xmm2
+	movaps	17(%eax), %xmm3
+	palignr	$15, %xmm2, %xmm3
+	palignr	$15, %xmm1, %xmm2
+
+	movaps	%xmm2, (%edx)
+	movaps	%xmm3, 16(%edx)
+	lea	32(%edx, %ecx), %edx
+	lea	32(%eax, %ecx), %eax
+	POP (%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	CFI_PUSH (%edi)
+
+	.p2align 4
+L(sh_15_no_prefetch):
+	lea	-32(%ecx), %ecx
+	lea	-15(%eax), %eax
+	xor	%edi, %edi
+
+	.p2align 4
+L(sh_15_no_prefetch_loop):
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
 	movdqa	32(%eax, %edi), %xmm3
@@ -1083,8 +1967,7 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(shl_15_end)
+	jb	L(sh_15_end_no_prefetch_loop)
 
 	movdqa	16(%eax, %edi), %xmm2
 	sub	$32, %ecx
@@ -1095,52 +1978,70 @@
 	lea	32(%edi), %edi
 	movdqa	%xmm2, -32(%edx, %edi)
 	movdqa	%xmm3, -16(%edx, %edi)
+	jae	L(sh_15_no_prefetch_loop)
 
-	jae	L(shl_15_loop)
-
-L(shl_15_end):
+L(sh_15_end_no_prefetch_loop):
 	lea	32(%ecx), %ecx
 	add	%ecx, %edi
 	add	%edi, %edx
 	lea	15(%edi, %eax), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY_TAIL(L(table_48bytes_fwd), %ecx, 4)
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
 
+	CFI_PUSH (%edi)
 
-	ALIGN (4)
+	.p2align 4
+L(shl_end_0):
+	lea	32(%ecx), %ecx
+	lea	(%edx, %ecx), %edx
+	lea	(%eax, %ecx), %eax
+	POP	(%edi)
+	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
+
+	.p2align 4
 L(fwd_write_44bytes):
-	movl	-44(%eax), %ecx
-	movl	%ecx, -44(%edx)
-L(fwd_write_40bytes):
-	movl	-40(%eax), %ecx
-	movl	%ecx, -40(%edx)
+	movq	-44(%eax), %xmm0
+	movq	%xmm0, -44(%edx)
 L(fwd_write_36bytes):
-	movl	-36(%eax), %ecx
-	movl	%ecx, -36(%edx)
-L(fwd_write_32bytes):
-	movl	-32(%eax), %ecx
-	movl	%ecx, -32(%edx)
+	movq	-36(%eax), %xmm0
+	movq	%xmm0, -36(%edx)
 L(fwd_write_28bytes):
-	movl	-28(%eax), %ecx
-	movl	%ecx, -28(%edx)
-L(fwd_write_24bytes):
-	movl	-24(%eax), %ecx
-	movl	%ecx, -24(%edx)
+	movq	-28(%eax), %xmm0
+	movq	%xmm0, -28(%edx)
 L(fwd_write_20bytes):
-	movl	-20(%eax), %ecx
-	movl	%ecx, -20(%edx)
-L(fwd_write_16bytes):
-	movl	-16(%eax), %ecx
-	movl	%ecx, -16(%edx)
+	movq	-20(%eax), %xmm0
+	movq	%xmm0, -20(%edx)
 L(fwd_write_12bytes):
-	movl	-12(%eax), %ecx
-	movl	%ecx, -12(%edx)
-L(fwd_write_8bytes):
-	movl	-8(%eax), %ecx
-	movl	%ecx, -8(%edx)
+	movq	-12(%eax), %xmm0
+	movq	%xmm0, -12(%edx)
 L(fwd_write_4bytes):
 	movl	-4(%eax), %ecx
 	movl	%ecx, -4(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_40bytes):
+	movq	-40(%eax), %xmm0
+	movq	%xmm0, -40(%edx)
+L(fwd_write_32bytes):
+	movq	-32(%eax), %xmm0
+	movq	%xmm0, -32(%edx)
+L(fwd_write_24bytes):
+	movq	-24(%eax), %xmm0
+	movq	%xmm0, -24(%edx)
+L(fwd_write_16bytes):
+	movq	-16(%eax), %xmm0
+	movq	%xmm0, -16(%edx)
+L(fwd_write_8bytes):
+	movq	-8(%eax), %xmm0
+	movq	%xmm0, -8(%edx)
 L(fwd_write_0bytes):
 #ifndef USE_AS_BCOPY
 # ifdef USE_AS_MEMPCPY
@@ -1151,7 +2052,7 @@
 #endif
 	RETURN
 
-	ALIGN (4)
+	.p2align 4
 L(fwd_write_5bytes):
 	movl	-5(%eax), %ecx
 	movl	-4(%eax), %eax
@@ -1166,39 +2067,51 @@
 #endif
 	RETURN
 
-	ALIGN (4)
+	.p2align 4
 L(fwd_write_45bytes):
-	movl	-45(%eax), %ecx
-	movl	%ecx, -45(%edx)
-L(fwd_write_41bytes):
-	movl	-41(%eax), %ecx
-	movl	%ecx, -41(%edx)
+	movq	-45(%eax), %xmm0
+	movq	%xmm0, -45(%edx)
 L(fwd_write_37bytes):
-	movl	-37(%eax), %ecx
-	movl	%ecx, -37(%edx)
-L(fwd_write_33bytes):
-	movl	-33(%eax), %ecx
-	movl	%ecx, -33(%edx)
+	movq	-37(%eax), %xmm0
+	movq	%xmm0, -37(%edx)
 L(fwd_write_29bytes):
-	movl	-29(%eax), %ecx
-	movl	%ecx, -29(%edx)
-L(fwd_write_25bytes):
-	movl	-25(%eax), %ecx
-	movl	%ecx, -25(%edx)
+	movq	-29(%eax), %xmm0
+	movq	%xmm0, -29(%edx)
 L(fwd_write_21bytes):
-	movl	-21(%eax), %ecx
-	movl	%ecx, -21(%edx)
-L(fwd_write_17bytes):
-	movl	-17(%eax), %ecx
-	movl	%ecx, -17(%edx)
+	movq	-21(%eax), %xmm0
+	movq	%xmm0, -21(%edx)
 L(fwd_write_13bytes):
-	movl	-13(%eax), %ecx
-	movl	%ecx, -13(%edx)
-L(fwd_write_9bytes):
-	movl	-9(%eax), %ecx
-	movl	%ecx, -9(%edx)
+	movq	-13(%eax), %xmm0
+	movq	%xmm0, -13(%edx)
 	movl	-5(%eax), %ecx
 	movl	%ecx, -5(%edx)
+	movzbl	-1(%eax), %ecx
+	movb	%cl, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_41bytes):
+	movq	-41(%eax), %xmm0
+	movq	%xmm0, -41(%edx)
+L(fwd_write_33bytes):
+	movq	-33(%eax), %xmm0
+	movq	%xmm0, -33(%edx)
+L(fwd_write_25bytes):
+	movq	-25(%eax), %xmm0
+	movq	%xmm0, -25(%edx)
+L(fwd_write_17bytes):
+	movq	-17(%eax), %xmm0
+	movq	%xmm0, -17(%edx)
+L(fwd_write_9bytes):
+	movq	-9(%eax), %xmm0
+	movq	%xmm0, -9(%edx)
 L(fwd_write_1bytes):
 	movzbl	-1(%eax), %ecx
 	movb	%cl, -1(%edx)
@@ -1211,40 +2124,52 @@
 #endif
 	RETURN
 
-	ALIGN (4)
+	.p2align 4
 L(fwd_write_46bytes):
-	movl	-46(%eax), %ecx
-	movl	%ecx, -46(%edx)
-L(fwd_write_42bytes):
-	movl	-42(%eax), %ecx
-	movl	%ecx, -42(%edx)
+	movq	-46(%eax), %xmm0
+	movq	%xmm0, -46(%edx)
 L(fwd_write_38bytes):
-	movl	-38(%eax), %ecx
-	movl	%ecx, -38(%edx)
-L(fwd_write_34bytes):
-	movl	-34(%eax), %ecx
-	movl	%ecx, -34(%edx)
+	movq	-38(%eax), %xmm0
+	movq	%xmm0, -38(%edx)
 L(fwd_write_30bytes):
-	movl	-30(%eax), %ecx
-	movl	%ecx, -30(%edx)
-L(fwd_write_26bytes):
-	movl	-26(%eax), %ecx
-	movl	%ecx, -26(%edx)
+	movq	-30(%eax), %xmm0
+	movq	%xmm0, -30(%edx)
 L(fwd_write_22bytes):
-	movl	-22(%eax), %ecx
-	movl	%ecx, -22(%edx)
-L(fwd_write_18bytes):
-	movl	-18(%eax), %ecx
-	movl	%ecx, -18(%edx)
+	movq	-22(%eax), %xmm0
+	movq	%xmm0, -22(%edx)
 L(fwd_write_14bytes):
-	movl	-14(%eax), %ecx
-	movl	%ecx, -14(%edx)
-L(fwd_write_10bytes):
-	movl	-10(%eax), %ecx
-	movl	%ecx, -10(%edx)
+	movq	-14(%eax), %xmm0
+	movq	%xmm0, -14(%edx)
 L(fwd_write_6bytes):
 	movl	-6(%eax), %ecx
 	movl	%ecx, -6(%edx)
+	movzwl	-2(%eax), %ecx
+	movw	%cx, -2(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_42bytes):
+	movq	-42(%eax), %xmm0
+	movq	%xmm0, -42(%edx)
+L(fwd_write_34bytes):
+	movq	-34(%eax), %xmm0
+	movq	%xmm0, -34(%edx)
+L(fwd_write_26bytes):
+	movq	-26(%eax), %xmm0
+	movq	%xmm0, -26(%edx)
+L(fwd_write_18bytes):
+	movq	-18(%eax), %xmm0
+	movq	%xmm0, -18(%edx)
+L(fwd_write_10bytes):
+	movq	-10(%eax), %xmm0
+	movq	%xmm0, -10(%edx)
 L(fwd_write_2bytes):
 	movzwl	-2(%eax), %ecx
 	movw	%cx, -2(%edx)
@@ -1257,40 +2182,54 @@
 #endif
 	RETURN
 
-	ALIGN (4)
+	.p2align 4
 L(fwd_write_47bytes):
-	movl	-47(%eax), %ecx
-	movl	%ecx, -47(%edx)
-L(fwd_write_43bytes):
-	movl	-43(%eax), %ecx
-	movl	%ecx, -43(%edx)
+	movq	-47(%eax), %xmm0
+	movq	%xmm0, -47(%edx)
 L(fwd_write_39bytes):
-	movl	-39(%eax), %ecx
-	movl	%ecx, -39(%edx)
-L(fwd_write_35bytes):
-	movl	-35(%eax), %ecx
-	movl	%ecx, -35(%edx)
+	movq	-39(%eax), %xmm0
+	movq	%xmm0, -39(%edx)
 L(fwd_write_31bytes):
-	movl	-31(%eax), %ecx
-	movl	%ecx, -31(%edx)
-L(fwd_write_27bytes):
-	movl	-27(%eax), %ecx
-	movl	%ecx, -27(%edx)
+	movq	-31(%eax), %xmm0
+	movq	%xmm0, -31(%edx)
 L(fwd_write_23bytes):
-	movl	-23(%eax), %ecx
-	movl	%ecx, -23(%edx)
-L(fwd_write_19bytes):
-	movl	-19(%eax), %ecx
-	movl	%ecx, -19(%edx)
+	movq	-23(%eax), %xmm0
+	movq	%xmm0, -23(%edx)
 L(fwd_write_15bytes):
-	movl	-15(%eax), %ecx
-	movl	%ecx, -15(%edx)
-L(fwd_write_11bytes):
-	movl	-11(%eax), %ecx
-	movl	%ecx, -11(%edx)
+	movq	-15(%eax), %xmm0
+	movq	%xmm0, -15(%edx)
 L(fwd_write_7bytes):
 	movl	-7(%eax), %ecx
 	movl	%ecx, -7(%edx)
+	movzwl	-3(%eax), %ecx
+	movzbl	-1(%eax), %eax
+	movw	%cx, -3(%edx)
+	movb	%al, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_43bytes):
+	movq	-43(%eax), %xmm0
+	movq	%xmm0, -43(%edx)
+L(fwd_write_35bytes):
+	movq	-35(%eax), %xmm0
+	movq	%xmm0, -35(%edx)
+L(fwd_write_27bytes):
+	movq	-27(%eax), %xmm0
+	movq	%xmm0, -27(%edx)
+L(fwd_write_19bytes):
+	movq	-19(%eax), %xmm0
+	movq	%xmm0, -19(%edx)
+L(fwd_write_11bytes):
+	movq	-11(%eax), %xmm0
+	movq	%xmm0, -11(%edx)
 L(fwd_write_3bytes):
 	movzwl	-3(%eax), %ecx
 	movzbl	-1(%eax), %eax
@@ -1303,20 +2242,374 @@
 	movl	DEST(%esp), %eax
 # endif
 #endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_40bytes_align):
+	movdqa	-40(%eax), %xmm0
+	movdqa	%xmm0, -40(%edx)
+L(fwd_write_24bytes_align):
+	movdqa	-24(%eax), %xmm0
+	movdqa	%xmm0, -24(%edx)
+L(fwd_write_8bytes_align):
+	movq	-8(%eax), %xmm0
+	movq	%xmm0, -8(%edx)
+L(fwd_write_0bytes_align):
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_32bytes_align):
+	movdqa	-32(%eax), %xmm0
+	movdqa	%xmm0, -32(%edx)
+L(fwd_write_16bytes_align):
+	movdqa	-16(%eax), %xmm0
+	movdqa	%xmm0, -16(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_5bytes_align):
+	movl	-5(%eax), %ecx
+	movl	-4(%eax), %eax
+	movl	%ecx, -5(%edx)
+	movl	%eax, -4(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_45bytes_align):
+	movdqa	-45(%eax), %xmm0
+	movdqa	%xmm0, -45(%edx)
+L(fwd_write_29bytes_align):
+	movdqa	-29(%eax), %xmm0
+	movdqa	%xmm0, -29(%edx)
+L(fwd_write_13bytes_align):
+	movq	-13(%eax), %xmm0
+	movq	%xmm0, -13(%edx)
+	movl	-5(%eax), %ecx
+	movl	%ecx, -5(%edx)
+	movzbl	-1(%eax), %ecx
+	movb	%cl, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_37bytes_align):
+	movdqa	-37(%eax), %xmm0
+	movdqa	%xmm0, -37(%edx)
+L(fwd_write_21bytes_align):
+	movdqa	-21(%eax), %xmm0
+	movdqa	%xmm0, -21(%edx)
+	movl	-5(%eax), %ecx
+	movl	%ecx, -5(%edx)
+	movzbl	-1(%eax), %ecx
+	movb	%cl, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_41bytes_align):
+	movdqa	-41(%eax), %xmm0
+	movdqa	%xmm0, -41(%edx)
+L(fwd_write_25bytes_align):
+	movdqa	-25(%eax), %xmm0
+	movdqa	%xmm0, -25(%edx)
+L(fwd_write_9bytes_align):
+	movq	-9(%eax), %xmm0
+	movq	%xmm0, -9(%edx)
+L(fwd_write_1bytes_align):
+	movzbl	-1(%eax), %ecx
+	movb	%cl, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_33bytes_align):
+	movdqa	-33(%eax), %xmm0
+	movdqa	%xmm0, -33(%edx)
+L(fwd_write_17bytes_align):
+	movdqa	-17(%eax), %xmm0
+	movdqa	%xmm0, -17(%edx)
+	movzbl	-1(%eax), %ecx
+	movb	%cl, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_46bytes_align):
+	movdqa	-46(%eax), %xmm0
+	movdqa	%xmm0, -46(%edx)
+L(fwd_write_30bytes_align):
+	movdqa	-30(%eax), %xmm0
+	movdqa	%xmm0, -30(%edx)
+L(fwd_write_14bytes_align):
+	movq	-14(%eax), %xmm0
+	movq	%xmm0, -14(%edx)
+L(fwd_write_6bytes_align):
+	movl	-6(%eax), %ecx
+	movl	%ecx, -6(%edx)
+	movzwl	-2(%eax), %ecx
+	movw	%cx, -2(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_38bytes_align):
+	movdqa	-38(%eax), %xmm0
+	movdqa	%xmm0, -38(%edx)
+L(fwd_write_22bytes_align):
+	movdqa	-22(%eax), %xmm0
+	movdqa	%xmm0, -22(%edx)
+	movl	-6(%eax), %ecx
+	movl	%ecx, -6(%edx)
+	movzwl	-2(%eax), %ecx
+	movw	%cx, -2(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_42bytes_align):
+	movdqa	-42(%eax), %xmm0
+	movdqa	%xmm0, -42(%edx)
+L(fwd_write_26bytes_align):
+	movdqa	-26(%eax), %xmm0
+	movdqa	%xmm0, -26(%edx)
+L(fwd_write_10bytes_align):
+	movq	-10(%eax), %xmm0
+	movq	%xmm0, -10(%edx)
+L(fwd_write_2bytes_align):
+	movzwl	-2(%eax), %ecx
+	movw	%cx, -2(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_34bytes_align):
+	movdqa	-34(%eax), %xmm0
+	movdqa	%xmm0, -34(%edx)
+L(fwd_write_18bytes_align):
+	movdqa	-18(%eax), %xmm0
+	movdqa	%xmm0, -18(%edx)
+	movzwl	-2(%eax), %ecx
+	movw	%cx, -2(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_47bytes_align):
+	movdqa	-47(%eax), %xmm0
+	movdqa	%xmm0, -47(%edx)
+L(fwd_write_31bytes_align):
+	movdqa	-31(%eax), %xmm0
+	movdqa	%xmm0, -31(%edx)
+L(fwd_write_15bytes_align):
+	movq	-15(%eax), %xmm0
+	movq	%xmm0, -15(%edx)
+L(fwd_write_7bytes_align):
+	movl	-7(%eax), %ecx
+	movl	%ecx, -7(%edx)
+	movzwl	-3(%eax), %ecx
+	movzbl	-1(%eax), %eax
+	movw	%cx, -3(%edx)
+	movb	%al, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_39bytes_align):
+	movdqa	-39(%eax), %xmm0
+	movdqa	%xmm0, -39(%edx)
+L(fwd_write_23bytes_align):
+	movdqa	-23(%eax), %xmm0
+	movdqa	%xmm0, -23(%edx)
+	movl	-7(%eax), %ecx
+	movl	%ecx, -7(%edx)
+	movzwl	-3(%eax), %ecx
+	movzbl	-1(%eax), %eax
+	movw	%cx, -3(%edx)
+	movb	%al, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_43bytes_align):
+	movdqa	-43(%eax), %xmm0
+	movdqa	%xmm0, -43(%edx)
+L(fwd_write_27bytes_align):
+	movdqa	-27(%eax), %xmm0
+	movdqa	%xmm0, -27(%edx)
+L(fwd_write_11bytes_align):
+	movq	-11(%eax), %xmm0
+	movq	%xmm0, -11(%edx)
+L(fwd_write_3bytes_align):
+	movzwl	-3(%eax), %ecx
+	movzbl	-1(%eax), %eax
+	movw	%cx, -3(%edx)
+	movb	%al, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_35bytes_align):
+	movdqa	-35(%eax), %xmm0
+	movdqa	%xmm0, -35(%edx)
+L(fwd_write_19bytes_align):
+	movdqa	-19(%eax), %xmm0
+	movdqa	%xmm0, -19(%edx)
+	movzwl	-3(%eax), %ecx
+	movzbl	-1(%eax), %eax
+	movw	%cx, -3(%edx)
+	movb	%al, -1(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_44bytes_align):
+	movdqa	-44(%eax), %xmm0
+	movdqa	%xmm0, -44(%edx)
+L(fwd_write_28bytes_align):
+	movdqa	-28(%eax), %xmm0
+	movdqa	%xmm0, -28(%edx)
+L(fwd_write_12bytes_align):
+	movq	-12(%eax), %xmm0
+	movq	%xmm0, -12(%edx)
+L(fwd_write_4bytes_align):
+	movl	-4(%eax), %ecx
+	movl	%ecx, -4(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(fwd_write_36bytes_align):
+	movdqa	-36(%eax), %xmm0
+	movdqa	%xmm0, -36(%edx)
+L(fwd_write_20bytes_align):
+	movdqa	-20(%eax), %xmm0
+	movdqa	%xmm0, -20(%edx)
+	movl	-4(%eax), %ecx
+	movl	%ecx, -4(%edx)
+#ifndef USE_AS_BCOPY
+# ifdef USE_AS_MEMPCPY
+	movl	%edx, %eax
+# else
+	movl	DEST(%esp), %eax
+# endif
+#endif
 	RETURN_END
 
-	cfi_restore_state
-	cfi_remember_state
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(large_page):
 	movdqu	(%eax), %xmm1
+#ifdef USE_AS_MEMMOVE
+	movl	DEST+4(%esp), %edi
+	movdqu	%xmm0, (%edi)
+#endif
 	lea	16(%eax), %eax
-	movdqu	%xmm0, (%esi)
 	movntdq	%xmm1, (%edx)
 	lea	16(%edx), %edx
-	POP (%esi)
 	lea	-0x90(%ecx), %ecx
 	POP (%edi)
+
+	.p2align 4
 L(large_page_loop):
 	movdqu	(%eax), %xmm0
 	movdqu	0x10(%eax), %xmm1
@@ -1371,38 +2664,22 @@
 	sfence
 	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd), %ecx, 4)
 
-
-	ALIGN (4)
+	.p2align 4
 L(bk_write_44bytes):
-	movl	40(%eax), %ecx
-	movl	%ecx, 40(%edx)
-L(bk_write_40bytes):
-	movl	36(%eax), %ecx
-	movl	%ecx, 36(%edx)
+	movq	36(%eax), %xmm0
+	movq	%xmm0, 36(%edx)
 L(bk_write_36bytes):
-	movl	32(%eax), %ecx
-	movl	%ecx, 32(%edx)
-L(bk_write_32bytes):
-	movl	28(%eax), %ecx
-	movl	%ecx, 28(%edx)
+	movq	28(%eax), %xmm0
+	movq	%xmm0, 28(%edx)
 L(bk_write_28bytes):
-	movl	24(%eax), %ecx
-	movl	%ecx, 24(%edx)
-L(bk_write_24bytes):
-	movl	20(%eax), %ecx
-	movl	%ecx, 20(%edx)
+	movq	20(%eax), %xmm0
+	movq	%xmm0, 20(%edx)
 L(bk_write_20bytes):
-	movl	16(%eax), %ecx
-	movl	%ecx, 16(%edx)
-L(bk_write_16bytes):
-	movl	12(%eax), %ecx
-	movl	%ecx, 12(%edx)
+	movq	12(%eax), %xmm0
+	movq	%xmm0, 12(%edx)
 L(bk_write_12bytes):
-	movl	8(%eax), %ecx
-	movl	%ecx, 8(%edx)
-L(bk_write_8bytes):
-	movl	4(%eax), %ecx
-	movl	%ecx, 4(%edx)
+	movq	4(%eax), %xmm0
+	movq	%xmm0, 4(%edx)
 L(bk_write_4bytes):
 	movl	(%eax), %ecx
 	movl	%ecx, (%edx)
@@ -1416,37 +2693,47 @@
 #endif
 	RETURN
 
-	ALIGN (4)
+	.p2align 4
+L(bk_write_40bytes):
+	movq	32(%eax), %xmm0
+	movq	%xmm0, 32(%edx)
+L(bk_write_32bytes):
+	movq	24(%eax), %xmm0
+	movq	%xmm0, 24(%edx)
+L(bk_write_24bytes):
+	movq	16(%eax), %xmm0
+	movq	%xmm0, 16(%edx)
+L(bk_write_16bytes):
+	movq	8(%eax), %xmm0
+	movq	%xmm0, 8(%edx)
+L(bk_write_8bytes):
+	movq	(%eax), %xmm0
+	movq	%xmm0, (%edx)
+#ifndef USE_AS_BCOPY
+	movl	DEST(%esp), %eax
+# ifdef USE_AS_MEMPCPY
+	movl	LEN(%esp), %ecx
+	add	%ecx, %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
 L(bk_write_45bytes):
-	movl	41(%eax), %ecx
-	movl	%ecx, 41(%edx)
-L(bk_write_41bytes):
-	movl	37(%eax), %ecx
-	movl	%ecx, 37(%edx)
+	movq	37(%eax), %xmm0
+	movq	%xmm0, 37(%edx)
 L(bk_write_37bytes):
-	movl	33(%eax), %ecx
-	movl	%ecx, 33(%edx)
-L(bk_write_33bytes):
-	movl	29(%eax), %ecx
-	movl	%ecx, 29(%edx)
+	movq	29(%eax), %xmm0
+	movq	%xmm0, 29(%edx)
 L(bk_write_29bytes):
-	movl	25(%eax), %ecx
-	movl	%ecx, 25(%edx)
-L(bk_write_25bytes):
-	movl	21(%eax), %ecx
-	movl	%ecx, 21(%edx)
+	movq	21(%eax), %xmm0
+	movq	%xmm0, 21(%edx)
 L(bk_write_21bytes):
-	movl	17(%eax), %ecx
-	movl	%ecx, 17(%edx)
-L(bk_write_17bytes):
-	movl	13(%eax), %ecx
-	movl	%ecx, 13(%edx)
+	movq	13(%eax), %xmm0
+	movq	%xmm0, 13(%edx)
 L(bk_write_13bytes):
-	movl	9(%eax), %ecx
-	movl	%ecx, 9(%edx)
-L(bk_write_9bytes):
-	movl	5(%eax), %ecx
-	movl	%ecx, 5(%edx)
+	movq	5(%eax), %xmm0
+	movq	%xmm0, 5(%edx)
 L(bk_write_5bytes):
 	movl	1(%eax), %ecx
 	movl	%ecx, 1(%edx)
@@ -1462,40 +2749,79 @@
 #endif
 	RETURN
 
-	ALIGN (4)
+	.p2align 4
+L(bk_write_41bytes):
+	movq	33(%eax), %xmm0
+	movq	%xmm0, 33(%edx)
+L(bk_write_33bytes):
+	movq	25(%eax), %xmm0
+	movq	%xmm0, 25(%edx)
+L(bk_write_25bytes):
+	movq	17(%eax), %xmm0
+	movq	%xmm0, 17(%edx)
+L(bk_write_17bytes):
+	movq	9(%eax), %xmm0
+	movq	%xmm0, 9(%edx)
+L(bk_write_9bytes):
+	movq	1(%eax), %xmm0
+	movq	%xmm0, 1(%edx)
+	movzbl	(%eax), %ecx
+	movb	%cl, (%edx)
+#ifndef USE_AS_BCOPY
+	movl	DEST(%esp), %eax
+# ifdef USE_AS_MEMPCPY
+	movl	LEN(%esp), %ecx
+	add	%ecx, %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
 L(bk_write_46bytes):
-	movl	42(%eax), %ecx
-	movl	%ecx, 42(%edx)
-L(bk_write_42bytes):
-	movl	38(%eax), %ecx
-	movl	%ecx, 38(%edx)
+	movq	38(%eax), %xmm0
+	movq	%xmm0, 38(%edx)
 L(bk_write_38bytes):
-	movl	34(%eax), %ecx
-	movl	%ecx, 34(%edx)
-L(bk_write_34bytes):
-	movl	30(%eax), %ecx
-	movl	%ecx, 30(%edx)
+	movq	30(%eax), %xmm0
+	movq	%xmm0, 30(%edx)
 L(bk_write_30bytes):
-	movl	26(%eax), %ecx
-	movl	%ecx, 26(%edx)
-L(bk_write_26bytes):
-	movl	22(%eax), %ecx
-	movl	%ecx, 22(%edx)
+	movq	22(%eax), %xmm0
+	movq	%xmm0, 22(%edx)
 L(bk_write_22bytes):
-	movl	18(%eax), %ecx
-	movl	%ecx, 18(%edx)
-L(bk_write_18bytes):
-	movl	14(%eax), %ecx
-	movl	%ecx, 14(%edx)
+	movq	14(%eax), %xmm0
+	movq	%xmm0, 14(%edx)
 L(bk_write_14bytes):
-	movl	10(%eax), %ecx
-	movl	%ecx, 10(%edx)
-L(bk_write_10bytes):
-	movl	6(%eax), %ecx
-	movl	%ecx, 6(%edx)
+	movq	6(%eax), %xmm0
+	movq	%xmm0, 6(%edx)
 L(bk_write_6bytes):
 	movl	2(%eax), %ecx
 	movl	%ecx, 2(%edx)
+	movzwl	(%eax), %ecx
+	movw	%cx, (%edx)
+#ifndef USE_AS_BCOPY
+	movl	DEST(%esp), %eax
+# ifdef USE_AS_MEMPCPY
+	movl	LEN(%esp), %ecx
+	add	%ecx, %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(bk_write_42bytes):
+	movq	34(%eax), %xmm0
+	movq	%xmm0, 34(%edx)
+L(bk_write_34bytes):
+	movq	26(%eax), %xmm0
+	movq	%xmm0, 26(%edx)
+L(bk_write_26bytes):
+	movq	18(%eax), %xmm0
+	movq	%xmm0, 18(%edx)
+L(bk_write_18bytes):
+	movq	10(%eax), %xmm0
+	movq	%xmm0, 10(%edx)
+L(bk_write_10bytes):
+	movq	2(%eax), %xmm0
+	movq	%xmm0, 2(%edx)
 L(bk_write_2bytes):
 	movzwl	(%eax), %ecx
 	movw	%cx, (%edx)
@@ -1508,40 +2834,54 @@
 #endif
 	RETURN
 
-	ALIGN (4)
+	.p2align 4
 L(bk_write_47bytes):
-	movl	43(%eax), %ecx
-	movl	%ecx, 43(%edx)
-L(bk_write_43bytes):
-	movl	39(%eax), %ecx
-	movl	%ecx, 39(%edx)
+	movq	39(%eax), %xmm0
+	movq	%xmm0, 39(%edx)
 L(bk_write_39bytes):
-	movl	35(%eax), %ecx
-	movl	%ecx, 35(%edx)
-L(bk_write_35bytes):
-	movl	31(%eax), %ecx
-	movl	%ecx, 31(%edx)
+	movq	31(%eax), %xmm0
+	movq	%xmm0, 31(%edx)
 L(bk_write_31bytes):
-	movl	27(%eax), %ecx
-	movl	%ecx, 27(%edx)
-L(bk_write_27bytes):
-	movl	23(%eax), %ecx
-	movl	%ecx, 23(%edx)
+	movq	23(%eax), %xmm0
+	movq	%xmm0, 23(%edx)
 L(bk_write_23bytes):
-	movl	19(%eax), %ecx
-	movl	%ecx, 19(%edx)
-L(bk_write_19bytes):
-	movl	15(%eax), %ecx
-	movl	%ecx, 15(%edx)
+	movq	15(%eax), %xmm0
+	movq	%xmm0, 15(%edx)
 L(bk_write_15bytes):
-	movl	11(%eax), %ecx
-	movl	%ecx, 11(%edx)
-L(bk_write_11bytes):
-	movl	7(%eax), %ecx
-	movl	%ecx, 7(%edx)
+	movq	7(%eax), %xmm0
+	movq	%xmm0, 7(%edx)
 L(bk_write_7bytes):
 	movl	3(%eax), %ecx
 	movl	%ecx, 3(%edx)
+	movzwl	1(%eax), %ecx
+	movw	%cx, 1(%edx)
+	movzbl	(%eax), %eax
+	movb	%al, (%edx)
+#ifndef USE_AS_BCOPY
+	movl	DEST(%esp), %eax
+# ifdef USE_AS_MEMPCPY
+	movl	LEN(%esp), %ecx
+	add	%ecx, %eax
+# endif
+#endif
+	RETURN
+
+	.p2align 4
+L(bk_write_43bytes):
+	movq	35(%eax), %xmm0
+	movq	%xmm0, 35(%edx)
+L(bk_write_35bytes):
+	movq	27(%eax), %xmm0
+	movq	%xmm0, 27(%edx)
+L(bk_write_27bytes):
+	movq	19(%eax), %xmm0
+	movq	%xmm0, 19(%edx)
+L(bk_write_19bytes):
+	movq	11(%eax), %xmm0
+	movq	%xmm0, 11(%edx)
+L(bk_write_11bytes):
+	movq	3(%eax), %xmm0
+	movq	%xmm0, 3(%edx)
 L(bk_write_3bytes):
 	movzwl	1(%eax), %ecx
 	movw	%cx, 1(%edx)
@@ -1558,7 +2898,7 @@
 
 
 	.pushsection .rodata.ssse3,"a",@progbits
-	ALIGN (2)
+	.p2align 2
 L(table_48bytes_fwd):
 	.int	JMPTBL (L(fwd_write_0bytes), L(table_48bytes_fwd))
 	.int	JMPTBL (L(fwd_write_1bytes), L(table_48bytes_fwd))
@@ -1609,7 +2949,58 @@
 	.int	JMPTBL (L(fwd_write_46bytes), L(table_48bytes_fwd))
 	.int	JMPTBL (L(fwd_write_47bytes), L(table_48bytes_fwd))
 
-	ALIGN (2)
+	.p2align 2
+L(table_48bytes_fwd_align):
+	.int	JMPTBL (L(fwd_write_0bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_1bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_2bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_3bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_4bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_5bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_6bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_7bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_8bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_9bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_10bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_11bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_12bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_13bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_14bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_15bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_16bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_17bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_18bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_19bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_20bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_21bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_22bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_23bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_24bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_25bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_26bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_27bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_28bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_29bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_30bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_31bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_32bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_33bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_34bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_35bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_36bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_37bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_38bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_39bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_40bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_41bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_42bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_43bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_44bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_45bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_46bytes_align), L(table_48bytes_fwd_align))
+	.int	JMPTBL (L(fwd_write_47bytes_align), L(table_48bytes_fwd_align))
+
+	.p2align 2
 L(shl_table):
 	.int	JMPTBL (L(shl_0), L(shl_table))
 	.int	JMPTBL (L(shl_1), L(shl_table))
@@ -1628,7 +3019,7 @@
 	.int	JMPTBL (L(shl_14), L(shl_table))
 	.int	JMPTBL (L(shl_15), L(shl_table))
 
-	ALIGN (2)
+	.p2align 2
 L(table_48_bytes_bwd):
 	.int	JMPTBL (L(bk_write_0bytes), L(table_48_bytes_bwd))
 	.int	JMPTBL (L(bk_write_1bytes), L(table_48_bytes_bwd))
@@ -1682,12 +3073,12 @@
 	.popsection
 
 #ifdef USE_AS_MEMMOVE
-	ALIGN (4)
+	.p2align 4
 L(copy_backward):
-	PUSH (%esi)
-	movl	%eax, %esi
+	PUSH (%edi)
+	movl	%eax, %edi
 	lea	(%ecx,%edx,1),%edx
-	lea	(%ecx,%esi,1),%esi
+	lea	(%ecx,%edi,1),%edi
 	testl	$0x3, %edx
 	jnz	L(bk_align)
 
@@ -1702,60 +3093,53 @@
 L(bk_write_more32bytes):
 	/* Copy 32 bytes at a time.  */
 	sub	$32, %ecx
-	movl	-4(%esi), %eax
-	movl	%eax, -4(%edx)
-	movl	-8(%esi), %eax
-	movl	%eax, -8(%edx)
-	movl	-12(%esi), %eax
-	movl	%eax, -12(%edx)
-	movl	-16(%esi), %eax
-	movl	%eax, -16(%edx)
-	movl	-20(%esi), %eax
-	movl	%eax, -20(%edx)
-	movl	-24(%esi), %eax
-	movl	%eax, -24(%edx)
-	movl	-28(%esi), %eax
-	movl	%eax, -28(%edx)
-	movl	-32(%esi), %eax
-	movl	%eax, -32(%edx)
+	movq	-8(%edi), %xmm0
+	movq	%xmm0, -8(%edx)
+	movq	-16(%edi), %xmm0
+	movq	%xmm0, -16(%edx)
+	movq	-24(%edi), %xmm0
+	movq	%xmm0, -24(%edx)
+	movq	-32(%edi), %xmm0
+	movq	%xmm0, -32(%edx)
 	sub	$32, %edx
-	sub	$32, %esi
+	sub	$32, %edi
 
 L(bk_write_less32bytes):
-	movl	%esi, %eax
+	movl	%edi, %eax
 	sub	%ecx, %edx
 	sub	%ecx, %eax
-	POP (%esi)
+	POP (%edi)
 L(bk_write_less32bytes_2):
 	BRANCH_TO_JMPTBL_ENTRY (L(table_48_bytes_bwd), %ecx, 4)
 
-	CFI_PUSH (%esi)
-	ALIGN (4)
+	CFI_PUSH (%edi)
+
+	.p2align 4
 L(bk_align):
 	cmp	$8, %ecx
 	jbe	L(bk_write_less32bytes)
 	testl	$1, %edx
 	/* We get here only if (EDX & 3 ) != 0 so if (EDX & 1) ==0,
-	   then (EDX & 2) must be != 0.  */
+	then	(EDX & 2) must be != 0.  */
 	jz	L(bk_got2)
-	sub	$1, %esi
+	sub	$1, %edi
 	sub	$1, %ecx
 	sub	$1, %edx
-	movzbl	(%esi), %eax
+	movzbl	(%edi), %eax
 	movb	%al, (%edx)
 
 	testl	$2, %edx
 	jz	L(bk_aligned_4)
 
 L(bk_got2):
-	sub	$2, %esi
+	sub	$2, %edi
 	sub	$2, %ecx
 	sub	$2, %edx
-	movzwl	(%esi), %eax
+	movzwl	(%edi), %eax
 	movw	%ax, (%edx)
 	jmp	L(bk_aligned_4)
 
-	ALIGN (4)
+	.p2align 4
 L(bk_write_more64bytes):
 	/* Check alignment of last byte.  */
 	testl	$15, %edx
@@ -1763,45 +3147,46 @@
 
 /* EDX is aligned 4 bytes, but not 16 bytes.  */
 L(bk_ssse3_align):
-	sub	$4, %esi
+	sub	$4, %edi
 	sub	$4, %ecx
 	sub	$4, %edx
-	movl	(%esi), %eax
+	movl	(%edi), %eax
 	movl	%eax, (%edx)
 
 	testl	$15, %edx
 	jz	L(bk_ssse3_cpy_pre)
 
-	sub	$4, %esi
+	sub	$4, %edi
 	sub	$4, %ecx
 	sub	$4, %edx
-	movl	(%esi), %eax
+	movl	(%edi), %eax
 	movl	%eax, (%edx)
 
 	testl	$15, %edx
 	jz	L(bk_ssse3_cpy_pre)
 
-	sub	$4, %esi
+	sub	$4, %edi
 	sub	$4, %ecx
 	sub	$4, %edx
-	movl	(%esi), %eax
+	movl	(%edi), %eax
 	movl	%eax, (%edx)
 
 L(bk_ssse3_cpy_pre):
 	cmp	$64, %ecx
 	jb	L(bk_write_more32bytes)
 
+	.p2align 4
 L(bk_ssse3_cpy):
-	sub	$64, %esi
+	sub	$64, %edi
 	sub	$64, %ecx
 	sub	$64, %edx
-	movdqu	0x30(%esi), %xmm3
+	movdqu	0x30(%edi), %xmm3
 	movdqa	%xmm3, 0x30(%edx)
-	movdqu	0x20(%esi), %xmm2
+	movdqu	0x20(%edi), %xmm2
 	movdqa	%xmm2, 0x20(%edx)
-	movdqu	0x10(%esi), %xmm1
+	movdqu	0x10(%edi), %xmm1
 	movdqa	%xmm1, 0x10(%edx)
-	movdqu	(%esi), %xmm0
+	movdqu	(%edi), %xmm0
 	movdqa	%xmm0, (%edx)
 	cmp	$64, %ecx
 	jae	L(bk_ssse3_cpy)
diff --git a/libc/bionic/logd_write.c b/libc/bionic/logd_write.c
index 2bc39fa..ac71689 100644
--- a/libc/bionic/logd_write.c
+++ b/libc/bionic/logd_write.c
@@ -64,6 +64,7 @@
     LOG_ID_NONE = 0,
     LOG_ID_MAIN,
     LOG_ID_RADIO,
+    LOG_ID_EVENTS,
     LOG_ID_MAX
 } log_id_t;
 
@@ -84,7 +85,8 @@
 static log_channel_t log_channels[LOG_ID_MAX] = {
     { __write_to_log_null, -1, NULL },
     { __write_to_log_init, -1, "/dev/"LOGGER_LOG_MAIN },
-    { __write_to_log_init, -1, "/dev/"LOGGER_LOG_RADIO }
+    { __write_to_log_init, -1, "/dev/"LOGGER_LOG_RADIO },
+    { __write_to_log_init, -1, "/dev/"LOGGER_LOG_EVENTS }
 };
 
 /* Important: see technical note at start of source file */
@@ -207,3 +209,41 @@
 
     return -1;
 }
+
+/*
+ * Event logging.
+ */
+
+// must be kept in sync with frameworks/base/core/java/android/util/EventLog.java
+typedef enum {
+    EVENT_TYPE_INT      = 0,
+    EVENT_TYPE_LONG     = 1,
+    EVENT_TYPE_STRING   = 2,
+    EVENT_TYPE_LIST     = 3,
+} AndroidEventLogType;
+
+static int __libc_android_log_btwrite(int32_t tag, char type, const void *payload, size_t len)
+{
+    struct iovec vec[3];
+
+    vec[0].iov_base = &tag;
+    vec[0].iov_len = sizeof(tag);
+    vec[1].iov_base = &type;
+    vec[1].iov_len = sizeof(type);
+    vec[2].iov_base = (void*)payload;
+    vec[2].iov_len = len;
+
+    return log_channels[LOG_ID_EVENTS].logger(LOG_ID_EVENTS, vec);
+}
+
+__LIBC_HIDDEN__
+void __libc_android_log_event_int(int32_t tag, int value)
+{
+    __libc_android_log_btwrite(tag, EVENT_TYPE_INT, &value, sizeof(value));
+}
+
+__LIBC_HIDDEN__
+void __libc_android_log_event_uid(int32_t tag)
+{
+    __libc_android_log_event_int(tag, getuid());
+}
diff --git a/libc/bionic/malloc_debug_leak.c b/libc/bionic/malloc_debug_leak.c
index 0b18645..316d5fe 100644
--- a/libc/bionic/malloc_debug_leak.c
+++ b/libc/bionic/malloc_debug_leak.c
@@ -25,26 +25,26 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
+#include <dlfcn.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <pthread.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <errno.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <fcntl.h>
 #include <unwind.h>
-#include <dlfcn.h>
 
-#include <sys/socket.h>
-#include <sys/un.h>
+#include <arpa/inet.h>
 #include <sys/select.h>
-#include <sys/types.h>
+#include <sys/socket.h>
 #include <sys/system_properties.h>
+#include <sys/types.h>
+#include <sys/un.h>
 
 #include "dlmalloc.h"
 #include "logd.h"
@@ -263,7 +263,12 @@
     // 1. allocate enough memory and include our header
     // 2. set the base pointer to be right after our header
 
-    void* base = dlmalloc(bytes + sizeof(AllocationEntry));
+    size_t size = bytes + sizeof(AllocationEntry);
+    if (size < bytes) { // Overflow.
+        return NULL;
+    }
+
+    void* base = dlmalloc(size);
     if (base != NULL) {
         pthread_mutex_lock(&gAllocationsMutex);
 
@@ -373,6 +378,10 @@
     // we will align by at least MALLOC_ALIGNMENT bytes
     // and at most alignment-MALLOC_ALIGNMENT bytes
     size_t size = (alignment-MALLOC_ALIGNMENT) + bytes;
+    if (size < bytes) { // Overflow.
+        return NULL;
+    }
+
     void* base = leak_malloc(size);
     if (base != NULL) {
         intptr_t ptr = (intptr_t)base;
diff --git a/libc/bionic/pthread-timers.c b/libc/bionic/pthread-timers.c
index ae04029..23d31df 100644
--- a/libc/bionic/pthread-timers.c
+++ b/libc/bionic/pthread-timers.c
@@ -9,7 +9,7 @@
  *    notice, this list of conditions and the following disclaimer.
  *  * Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the 
+ *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -19,55 +19,56 @@
  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #include "pthread_internal.h"
-#include <linux/time.h>
-#include <string.h>
+
 #include <errno.h>
+#include <linux/time.h>
+#include <stdio.h>
+#include <string.h>
 
-/* This file implements the support required to implement SIGEV_THREAD posix 
- * timers. See the following pages for additionnal details:
- *
- * www.opengroup.org/onlinepubs/000095399/functions/timer_create.html
- * www.opengroup.org/onlinepubs/000095399/functions/timer_settime.html
- * www.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_04.html#tag_02_04_01
- *
- * The Linux kernel doesn't support these, so we need to implement them in the
- * C library. We use a very basic scheme where each timer is associated to a
- * thread that will loop, waiting for timeouts or messages from the program
- * corresponding to calls to timer_settime() and timer_delete().
- *
- * Note also an important thing: Posix mandates that in the case of fork(),
- * the timers of the child process should be disarmed, but not deleted.
- * this is implemented by providing a fork() wrapper (see bionic/fork.c) which
- * stops all timers before the fork, and only re-start them in case of error
- * or in the parent process.
- *
- * the stop/start is implemented by the __timer_table_start_stop() function
- * below.
- */
-
-/* normal (i.e. non-SIGEV_THREAD) timer ids are created directly by the kernel
- * and are passed as is to/from the caller.
- *
- * on the other hand, a SIGEV_THREAD timer ID will have its TIMER_ID_WRAP_BIT
- * always set to 1. In this implementation, this is always bit 31, which is
- * guaranteed to never be used by kernel-provided timer ids
- *
- * (see code in <kernel>/lib/idr.c, used to manage IDs, to see why)
- */
+// Normal (i.e. non-SIGEV_THREAD) timers are created directly by the kernel
+// and are passed as is to/from the caller.
+//
+// This file also implements the support required for SIGEV_THREAD ("POSIX interval")
+// timers. See the following pages for additional details:
+//
+// www.opengroup.org/onlinepubs/000095399/functions/timer_create.html
+// www.opengroup.org/onlinepubs/000095399/functions/timer_settime.html
+// www.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_04.html#tag_02_04_01
+//
+// The Linux kernel doesn't support these, so we need to implement them in the
+// C library. We use a very basic scheme where each timer is associated to a
+// thread that will loop, waiting for timeouts or messages from the program
+// corresponding to calls to timer_settime() and timer_delete().
+//
+// Note also an important thing: Posix mandates that in the case of fork(),
+// the timers of the child process should be disarmed, but not deleted.
+// this is implemented by providing a fork() wrapper (see bionic/fork.c) which
+// stops all timers before the fork, and only re-start them in case of error
+// or in the parent process.
+//
+// This stop/start is implemented by the __timer_table_start_stop() function
+// below.
+//
+// A SIGEV_THREAD timer ID will always have its TIMER_ID_WRAP_BIT
+// set to 1. In this implementation, this is always bit 31, which is
+// guaranteed to never be used by kernel-provided timer ids
+//
+// (See code in <kernel>/lib/idr.c, used to manage IDs, to see why.)
 
 #define  TIMER_ID_WRAP_BIT        0x80000000
 #define  TIMER_ID_WRAP(id)        ((timer_t)((id) |  TIMER_ID_WRAP_BIT))
 #define  TIMER_ID_UNWRAP(id)      ((timer_t)((id) & ~TIMER_ID_WRAP_BIT))
 #define  TIMER_ID_IS_WRAPPED(id)  (((id) & TIMER_ID_WRAP_BIT) != 0)
 
-/* this value is used internally to indicate a 'free' or 'zombie' 
+/* this value is used internally to indicate a 'free' or 'zombie'
  * thr_timer structure. Here, 'zombie' means that timer_delete()
  * has been called, but that the corresponding thread hasn't
  * exited yet.
@@ -171,25 +172,23 @@
 }
 
 
-static void
-thr_timer_table_start_stop( thr_timer_table_t*  t, int  stop )
-{
-    int  nn;
+static void thr_timer_table_start_stop(thr_timer_table_t* t, int stop) {
+  if (t == NULL) {
+    return;
+  }
 
-    pthread_mutex_lock(&t->lock);
-
-    for (nn = 0; nn < MAX_THREAD_TIMERS; nn++) {
-        thr_timer_t*  timer  = &t->timers[nn];
-
-        if (TIMER_ID_IS_VALID(timer->id)) {
-            /* tell the thread to start/stop */
-            pthread_mutex_lock(&timer->mutex);
-            timer->stopped = stop;
-            pthread_cond_signal( &timer->cond );
-            pthread_mutex_unlock(&timer->mutex);
-        }
+  pthread_mutex_lock(&t->lock);
+  for (int nn = 0; nn < MAX_THREAD_TIMERS; ++nn) {
+    thr_timer_t*  timer  = &t->timers[nn];
+    if (TIMER_ID_IS_VALID(timer->id)) {
+      // Tell the thread to start/stop.
+      pthread_mutex_lock(&timer->mutex);
+      timer->stopped = stop;
+      pthread_cond_signal( &timer->cond );
+      pthread_mutex_unlock(&timer->mutex);
     }
-    pthread_mutex_unlock(&t->lock);
+  }
+  pthread_mutex_unlock(&t->lock);
 }
 
 
@@ -234,23 +233,19 @@
  * pretty infrequent
  */
 
-static pthread_once_t      __timer_table_once = PTHREAD_ONCE_INIT;
-static thr_timer_table_t*  __timer_table;
+static pthread_once_t __timer_table_once = PTHREAD_ONCE_INIT;
+static thr_timer_table_t* __timer_table;
 
-static void
-__timer_table_init( void )
-{
-    __timer_table = calloc(1,sizeof(*__timer_table));
-
-    if (__timer_table != NULL)
-        thr_timer_table_init( __timer_table );
+static void __timer_table_init(void) {
+  __timer_table = calloc(1, sizeof(*__timer_table));
+  if (__timer_table != NULL) {
+    thr_timer_table_init(__timer_table);
+  }
 }
 
-static thr_timer_table_t*
-__timer_table_get(void)
-{
-    pthread_once( &__timer_table_once, __timer_table_init );
-    return __timer_table;
+static thr_timer_table_t* __timer_table_get(void) {
+  pthread_once(&__timer_table_once, __timer_table_init);
+  return __timer_table;
 }
 
 /** POSIX THREAD TIMERS CLEANUP ON FORK
@@ -260,13 +255,9 @@
  ** requirements: the timers of fork child processes must be
  ** disarmed but not deleted.
  **/
-__LIBC_HIDDEN__ void
-__timer_table_start_stop( int  stop )
-{
-    if (__timer_table != NULL) {
-        thr_timer_table_t*  table = __timer_table_get();
-        thr_timer_table_start_stop(table, stop);
-    }
+__LIBC_HIDDEN__ void __timer_table_start_stop(int stop) {
+  // We access __timer_table directly so we don't create it if it doesn't yet exist.
+  thr_timer_table_start_stop(__timer_table, stop);
 }
 
 static thr_timer_t*
@@ -293,85 +284,76 @@
 
 /** POSIX TIMERS APIs */
 
-/* first, declare the syscall stubs */
-extern int __timer_create( clockid_t, struct sigevent*, timer_t* );
-extern int __timer_delete( timer_t );
-extern int __timer_gettime( timer_t, struct itimerspec* );
-extern int __timer_settime( timer_t, int, const struct itimerspec*, struct itimerspec* );
+extern int __timer_create(clockid_t, struct sigevent*, timer_t*);
+extern int __timer_delete(timer_t);
+extern int __timer_gettime(timer_t, struct itimerspec*);
+extern int __timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*);
 extern int __timer_getoverrun(timer_t);
 
-static void*  timer_thread_start( void* );
+static void* timer_thread_start(void*);
 
-/* then the wrappers themselves */
-int
-timer_create( clockid_t  clockid, struct sigevent*  evp, timer_t  *ptimerid)
-{
-    /* if not a SIGEV_THREAD timer, direct creation by the kernel */
-    if (__likely(evp == NULL || evp->sigev_notify != SIGEV_THREAD))
-        return __timer_create( clockid, evp, ptimerid );
+int timer_create(clockid_t clock_id, struct sigevent* evp, timer_t* timer_id) {
+  // If not a SIGEV_THREAD timer, the kernel can handle it without our help.
+  if (__likely(evp == NULL || evp->sigev_notify != SIGEV_THREAD)) {
+    return __timer_create(clock_id, evp, timer_id);
+  }
 
-    // check arguments
-    if (evp->sigev_notify_function == NULL) {
-        errno = EINVAL;
-        return -1;
-    }
+  // Check arguments.
+  if (evp->sigev_notify_function == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
 
-    {
-        struct timespec  dummy;
+  // Check that the clock id is supported by the kernel.
+  struct timespec dummy;
+  if (clock_gettime(clock_id, &dummy) < 0 && errno == EINVAL) {
+    return -1;
+  }
 
-        /* check that the clock id is supported by the kernel */
-        if (clock_gettime( clockid, &dummy ) < 0 && errno == EINVAL )
-            return -1;
-    }
+  // Create a new timer and its thread.
+  // TODO: use a single global thread for all timers.
+  thr_timer_table_t* table = __timer_table_get();
+  thr_timer_t* timer = thr_timer_table_alloc(table);
+  if (timer == NULL) {
+    errno = ENOMEM;
+    return -1;
+  }
 
-    /* create a new timer and its thread */
-    {
-        thr_timer_table_t*  table = __timer_table_get();
-        thr_timer_t*        timer = thr_timer_table_alloc( table );
-        struct sigevent     evp0;
+  // Copy the thread attributes.
+  if (evp->sigev_notify_attributes == NULL) {
+    pthread_attr_init(&timer->attributes);
+  } else {
+    timer->attributes = ((pthread_attr_t*) evp->sigev_notify_attributes)[0];
+  }
 
-        if (timer == NULL) {
-            errno = ENOMEM;
-            return -1;
-        }
+  // Posix says that the default is PTHREAD_CREATE_DETACHED and
+  // that PTHREAD_CREATE_JOINABLE has undefined behavior.
+  // So simply always use DETACHED :-)
+  pthread_attr_setdetachstate(&timer->attributes, PTHREAD_CREATE_DETACHED);
 
-        /* copy the thread attributes */
-        if (evp->sigev_notify_attributes == NULL) {
-            pthread_attr_init(&timer->attributes);
-        }
-        else {
-            timer->attributes = ((pthread_attr_t*)evp->sigev_notify_attributes)[0];
-        }
+  timer->callback = evp->sigev_notify_function;
+  timer->value = evp->sigev_value;
+  timer->clock = clock_id;
 
-        /* Posix says that the default is PTHREAD_CREATE_DETACHED and
-         * that PTHREAD_CREATE_JOINABLE has undefined behaviour.
-         * So simply always use DETACHED :-)
-         */
-        pthread_attr_setdetachstate(&timer->attributes, PTHREAD_CREATE_DETACHED);
+  pthread_mutex_init(&timer->mutex, NULL);
+  pthread_cond_init(&timer->cond, NULL);
 
-        timer->callback = evp->sigev_notify_function;
-        timer->value    = evp->sigev_value;
-        timer->clock    = clockid;
+  timer->done = 0;
+  timer->stopped = 0;
+  timer->expires.tv_sec = timer->expires.tv_nsec = 0;
+  timer->period.tv_sec = timer->period.tv_nsec  = 0;
+  timer->overruns = 0;
 
-        pthread_mutex_init( &timer->mutex, NULL );
-        pthread_cond_init( &timer->cond, NULL );
+  // Create the thread.
+  int rc = pthread_create(&timer->thread, &timer->attributes, timer_thread_start, timer);
+  if (rc != 0) {
+    thr_timer_table_free(table, timer);
+    errno = rc;
+    return -1;
+  }
 
-        timer->done           = 0;
-        timer->stopped        = 0;
-        timer->expires.tv_sec = timer->expires.tv_nsec = 0;
-        timer->period.tv_sec  = timer->period.tv_nsec  = 0;
-        timer->overruns       = 0;
-
-        /* create the thread */
-        if (pthread_create( &timer->thread, &timer->attributes, timer_thread_start, timer ) < 0) {
-            thr_timer_table_free( __timer_table, timer );
-            errno = ENOMEM;
-            return -1;
-        }
-
-        *ptimerid = timer->id;
-        return 0;
-    }
+  *timer_id = timer->id;
+  return 0;
 }
 
 
@@ -414,7 +396,7 @@
     struct timespec  diff;
 
     diff = timer->expires;
-    if (!timespec_is_zero(&diff)) 
+    if (!timespec_is_zero(&diff))
     {
         struct timespec  now;
 
@@ -532,108 +514,93 @@
 }
 
 
-static void*
-timer_thread_start( void*  _arg )
-{
-    thr_timer_t*  timer = _arg;
+static void* timer_thread_start(void* arg) {
+  thr_timer_t* timer = arg;
 
-    thr_timer_lock( timer );
+  thr_timer_lock(timer);
 
-    /* we loop until timer->done is set in timer_delete() */
-    while (!timer->done) 
-    {
-        struct timespec   expires = timer->expires;
-        struct timespec   period  = timer->period;
-        struct timespec   now;
+  // Give this thread a meaningful name.
+  char name[32];
+  snprintf(name, sizeof(name), "POSIX interval timer 0x%08x", timer->id);
+  pthread_setname_np(pthread_self(), name);
 
-        /* if the timer is stopped or disarmed, wait indefinitely
-         * for a state change from timer_settime/_delete/_start_stop
-         */
-        if ( timer->stopped || timespec_is_zero(&expires) )
-        {
-            pthread_cond_wait( &timer->cond, &timer->mutex );
-            continue;
-        }
+  // We loop until timer->done is set in timer_delete().
+  while (!timer->done) {
+    struct timespec expires = timer->expires;
+    struct timespec period = timer->period;
 
-        /* otherwise, we need to do a timed wait until either a
-        * state change of the timer expiration time.
-        */
-        clock_gettime(timer->clock, &now);
-
-        if (timespec_cmp( &expires, &now ) > 0)
-        {
-            /* cool, there was no overrun, so compute the
-             * relative timeout as 'expires - now', then wait
-             */
-            int              ret;
-            struct timespec  diff = expires;
-            timespec_sub( &diff, &now );
-
-            ret = __pthread_cond_timedwait_relative(
-                        &timer->cond, &timer->mutex, &diff);
-
-            /* if we didn't timeout, it means that a state change
-                * occured, so reloop to take care of it.
-                */
-            if (ret != ETIMEDOUT)
-                continue;
-        }
-        else
-        {
-            /* overrun was detected before we could wait ! */
-            if (!timespec_is_zero( &period ) )
-            {
-                /* for periodic timers, compute total overrun count */
-                do {
-                    timespec_add( &expires, &period );
-                    if (timer->overruns < DELAYTIMER_MAX)
-                        timer->overruns += 1;
-                } while ( timespec_cmp( &expires, &now ) < 0 );
-
-                /* backtrack the last one, because we're going to
-                 * add the same value just a bit later */
-                timespec_sub( &expires, &period );
-            }
-            else
-            {
-                /* for non-periodic timer, things are simple */
-                timer->overruns = 1;
-            }
-        }
-
-        /* if we get there, a timeout was detected.
-         * first reload/disarm the timer has needed
-         */
-        if ( !timespec_is_zero(&period) ) {
-            timespec_add( &expires, &period );
-        } else {
-            timespec_zero( &expires );
-        }
-        timer->expires = expires;
-
-        /* now call the timer callback function. release the
-         * lock to allow the function to modify the timer setting
-         * or call timer_getoverrun().
-         *
-         * NOTE: at this point we trust the callback not to be a
-         *       total moron and pthread_kill() the timer thread
-         */
-        thr_timer_unlock(timer);
-        timer->callback( timer->value );
-        thr_timer_lock(timer);
-
-        /* now clear the overruns counter. it only makes sense
-         * within the callback */
-        timer->overruns = 0;
+    // If the timer is stopped or disarmed, wait indefinitely
+    // for a state change from timer_settime/_delete/_start_stop.
+    if (timer->stopped || timespec_is_zero(&expires)) {
+      pthread_cond_wait(&timer->cond, &timer->mutex);
+      continue;
     }
 
-    thr_timer_unlock( timer );
+    // Otherwise, we need to do a timed wait until either a
+    // state change of the timer expiration time.
+    struct timespec now;
+    clock_gettime(timer->clock, &now);
 
-    /* free the timer object now. there is no need to call
-     * __timer_table_get() since we're guaranteed that __timer_table
-     * is initialized in this thread
-     */
-    thr_timer_table_free(__timer_table, timer);
+    if (timespec_cmp(&expires, &now) > 0) {
+      // Cool, there was no overrun, so compute the
+      // relative timeout as 'expires - now', then wait.
+      struct timespec diff = expires;
+      timespec_sub(&diff, &now);
 
-    return NULL;
+      int ret = __pthread_cond_timedwait_relative(&timer->cond, &timer->mutex, &diff);
+
+      // If we didn't time out, it means that a state change
+      // occurred, so loop to take care of it.
+      if (ret != ETIMEDOUT) {
+        continue;
+      }
+    } else {
+      // Overrun was detected before we could wait!
+      if (!timespec_is_zero(&period)) {
+        // For periodic timers, compute total overrun count.
+        do {
+          timespec_add(&expires, &period);
+          if (timer->overruns < DELAYTIMER_MAX) {
+            timer->overruns += 1;
+          }
+        } while (timespec_cmp(&expires, &now) < 0);
+
+        // Backtrack the last one, because we're going to
+        // add the same value just a bit later.
+        timespec_sub(&expires, &period);
+      } else {
+        // For non-periodic timers, things are simple.
+        timer->overruns = 1;
+      }
+    }
+
+    // If we get here, a timeout was detected.
+    // First reload/disarm the timer as needed.
+    if (!timespec_is_zero(&period)) {
+      timespec_add(&expires, &period);
+    } else {
+      timespec_zero(&expires);
+    }
+    timer->expires = expires;
+
+    // Now call the timer callback function. Release the
+    // lock to allow the function to modify the timer setting
+    // or call timer_getoverrun().
+    // NOTE: at this point we trust the callback not to be a
+    //      total moron and pthread_kill() the timer thread
+    thr_timer_unlock(timer);
+    timer->callback(timer->value);
+    thr_timer_lock(timer);
+
+    // Now clear the overruns counter. it only makes sense
+    // within the callback.
+    timer->overruns = 0;
+  }
+
+  thr_timer_unlock(timer);
+
+  // Free the timer object.
+  thr_timer_table_free(__timer_table_get(), timer);
+
+  return NULL;
 }
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index 5cad167..2e2c09d 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -25,31 +25,32 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <sys/types.h>
-#include <unistd.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <malloc.h>
+#include <memory.h>
+#include <pthread.h>
 #include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
 #include <sys/atomics.h>
-#include <bionic_tls.h>
 #include <sys/mman.h>
-#include <pthread.h>
-#include <time.h>
-#include "pthread_internal.h"
-#include "thread_private.h"
-#include <limits.h>
-#include <memory.h>
-#include <assert.h>
-#include <malloc.h>
-#include <bionic_futex.h>
-#include <bionic_atomic_inline.h>
 #include <sys/prctl.h>
 #include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <bionic_pthread.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "bionic_atomic_inline.h"
+#include "bionic_futex.h"
+#include "bionic_pthread.h"
+#include "bionic_tls.h"
+#include "pthread_internal.h"
+#include "thread_private.h"
 
 extern void pthread_debug_mutex_lock_check(pthread_mutex_t *mutex);
 extern void pthread_debug_mutex_unlock_check(pthread_mutex_t *mutex);
@@ -80,6 +81,8 @@
 
 void ATTRIBUTES _thread_created_hook(pid_t thread_id);
 
+static const int kPthreadInitFailed = 1;
+
 #define PTHREAD_ATTR_FLAG_DETACHED      0x00000001
 #define PTHREAD_ATTR_FLAG_USER_STACK    0x00000002
 
@@ -97,35 +100,16 @@
     .sched_priority = 0
 };
 
-#define  INIT_THREADS  1
-
-static pthread_internal_t*  gThreadList = NULL;
+static pthread_internal_t* gThreadList = NULL;
 static pthread_mutex_t gThreadListLock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t gDebuggerNotificationLock = PTHREAD_MUTEX_INITIALIZER;
 
 
-/* we simply malloc/free the internal pthread_internal_t structures. we may
- * want to use a different allocation scheme in the future, but this one should
- * be largely enough
- */
-static pthread_internal_t*
-_pthread_internal_alloc(void)
-{
-    pthread_internal_t*   thread;
-
-    thread = calloc( sizeof(*thread), 1 );
-    if (thread)
-        thread->intern = 1;
-
-    return thread;
-}
-
 static void
-_pthread_internal_free( pthread_internal_t*  thread )
+_pthread_internal_free(pthread_internal_t* thread)
 {
-    if (thread && thread->intern) {
-        thread->intern = 0;  /* just in case */
-        free (thread);
+    if (thread != NULL) {
+        free(thread);
     }
 }
 
@@ -194,32 +178,35 @@
 
 
 /*
- * This trampoline is called from the assembly clone() function
+ * This trampoline is called from the assembly _pthread_clone() function.
  */
 void __thread_entry(int (*func)(void*), void *arg, void **tls)
 {
-    int retValue;
-    pthread_internal_t * thrInfo;
-
     // Wait for our creating thread to release us. This lets it have time to
-    // notify gdb about this thread before it starts doing anything.
+    // notify gdb about this thread before we start doing anything.
     //
     // This also provides the memory barrier needed to ensure that all memory
     // accesses previously made by the creating thread are visible to us.
-    pthread_mutex_t * start_mutex = (pthread_mutex_t *)&tls[TLS_SLOT_SELF];
+    pthread_mutex_t* start_mutex = (pthread_mutex_t*) &tls[TLS_SLOT_SELF];
     pthread_mutex_lock(start_mutex);
     pthread_mutex_destroy(start_mutex);
 
-    thrInfo = (pthread_internal_t *) tls[TLS_SLOT_THREAD_ID];
+    pthread_internal_t* thread = (pthread_internal_t*) tls[TLS_SLOT_THREAD_ID];
+    __init_tls(tls, thread);
 
-    __init_tls( tls, thrInfo );
+    if ((thread->internal_flags & kPthreadInitFailed) != 0) {
+        pthread_exit(NULL);
+    }
 
-    pthread_exit( (void*)func(arg) );
+    int result = func(arg);
+    pthread_exit((void*) result);
 }
 
 __LIBC_ABI_PRIVATE__
-void _init_thread(pthread_internal_t * thread, pid_t kernel_id, pthread_attr_t * attr, void * stack_base)
+int _init_thread(pthread_internal_t * thread, pid_t kernel_id, pthread_attr_t * attr, void * stack_base)
 {
+    int error = 0;
+
     if (attr == NULL) {
         thread->attr = gDefaultPthreadAttr;
     } else {
@@ -228,40 +215,42 @@
     thread->attr.stack_base = stack_base;
     thread->kernel_id       = kernel_id;
 
-    // set the scheduling policy/priority of the thread
+    // Make a note of whether the user supplied this stack (so we know whether or not to free it).
+    if (attr->stack_base == stack_base) {
+        thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_STACK;
+    }
+
+    // Set the scheduling policy/priority of the thread.
     if (thread->attr.sched_policy != SCHED_NORMAL) {
         struct sched_param param;
         param.sched_priority = thread->attr.sched_priority;
-        sched_setscheduler(kernel_id, thread->attr.sched_policy, &param);
+        if (sched_setscheduler(kernel_id, thread->attr.sched_policy, &param) == -1) {
+            error = errno;
+        }
     }
 
     pthread_cond_init(&thread->join_cond, NULL);
     thread->join_count = 0;
 
     thread->cleanup_stack = NULL;
+
+    _pthread_internal_add(thread);
+    return error;
 }
 
-
-/* XXX stacks not reclaimed if thread spawn fails */
-/* XXX stacks address spaces should be reused if available again */
-
 static void *mkstack(size_t size, size_t guard_size)
 {
-    void * stack;
-
     pthread_mutex_lock(&mmap_lock);
 
-    stack = mmap(NULL, size,
-                 PROT_READ | PROT_WRITE,
-                 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
-                 -1, 0);
-
-    if(stack == MAP_FAILED) {
+    int prot = PROT_READ | PROT_WRITE;
+    int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
+    void* stack = mmap(NULL, size, prot, flags, -1, 0);
+    if (stack == MAP_FAILED) {
         stack = NULL;
         goto done;
     }
 
-    if(mprotect(stack, guard_size, PROT_NONE)){
+    if (mprotect(stack, guard_size, PROT_NONE) == -1) {
         munmap(stack, size);
         stack = NULL;
         goto done;
@@ -298,13 +287,7 @@
 int pthread_create(pthread_t *thread_out, pthread_attr_t const * attr,
                    void *(*start_routine)(void *), void * arg)
 {
-    char*   stack;
-    void**  tls;
-    int tid;
-    pthread_mutex_t * start_mutex;
-    pthread_internal_t * thread;
-    int                  madestack = 0;
-    int     old_errno = errno;
+    int old_errno = errno;
 
     /* this will inform the rest of the C library that at least one thread
      * was created. this will enforce certain functions to acquire/release
@@ -315,31 +298,28 @@
      */
     __isthreaded = 1;
 
-    thread = _pthread_internal_alloc();
-    if (thread == NULL)
+    pthread_internal_t* thread = calloc(sizeof(*thread), 1);
+    if (thread == NULL) {
         return ENOMEM;
+    }
 
     if (attr == NULL) {
         attr = &gDefaultPthreadAttr;
     }
 
     // make sure the stack is PAGE_SIZE aligned
-    size_t stackSize = (attr->stack_size +
-                        (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
-
-    if (!attr->stack_base) {
-        stack = mkstack(stackSize, attr->guard_size);
-        if(stack == NULL) {
+    size_t stack_size = (attr->stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+    uint8_t* stack = attr->stack_base;
+    if (stack == NULL) {
+        stack = mkstack(stack_size, attr->guard_size);
+        if (stack == NULL) {
             _pthread_internal_free(thread);
             return ENOMEM;
         }
-        madestack = 1;
-    } else {
-        stack = attr->stack_base;
     }
 
     // Make room for TLS
-    tls = (void**)(stack + stackSize - BIONIC_TLS_SLOTS*sizeof(void*));
+    void** tls = (void**)(stack + stack_size - BIONIC_TLS_SLOTS*sizeof(void*));
 
     // Create a mutex for the thread in TLS_SLOT_SELF to wait on once it starts so we can keep
     // it from doing anything until after we notify the debugger about it
@@ -347,43 +327,47 @@
     // This also provides the memory barrier we need to ensure that all
     // memory accesses previously performed by this thread are visible to
     // the new thread.
-    start_mutex = (pthread_mutex_t *) &tls[TLS_SLOT_SELF];
+    pthread_mutex_t* start_mutex = (pthread_mutex_t*) &tls[TLS_SLOT_SELF];
     pthread_mutex_init(start_mutex, NULL);
     pthread_mutex_lock(start_mutex);
 
     tls[TLS_SLOT_THREAD_ID] = thread;
 
-    tid = __pthread_clone((int(*)(void*))start_routine, tls,
-                CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND
-                | CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED,
-                arg);
+    int flags = CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND |
+                CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED;
+    int tid = __pthread_clone((int(*)(void*))start_routine, tls, flags, arg);
 
-    if(tid < 0) {
-        int  result;
-        if (madestack)
-            munmap(stack, stackSize);
+    if (tid < 0) {
+        int clone_errno = errno;
+        pthread_mutex_unlock(start_mutex);
+        if (stack != attr->stack_base) {
+            munmap(stack, stack_size);
+        }
         _pthread_internal_free(thread);
-        result = errno;
         errno = old_errno;
-        return result;
+        return clone_errno;
     }
 
-    _init_thread(thread, tid, (pthread_attr_t*)attr, stack);
+    int init_errno = _init_thread(thread, tid, (pthread_attr_t*) attr, stack);
+    if (init_errno != 0) {
+        // Mark the thread detached and let its __thread_entry run to
+        // completion. (It'll just exit immediately, cleaning up its resources.)
+        thread->internal_flags |= kPthreadInitFailed;
+        thread->attr.flags |= PTHREAD_ATTR_FLAG_DETACHED;
+        pthread_mutex_unlock(start_mutex);
+        errno = old_errno;
+        return init_errno;
+    }
 
-    _pthread_internal_add(thread);
-
-    if (!madestack)
-        thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_STACK;
-
-    // Notify any debuggers about the new thread
+    // Notify any debuggers about the new thread.
     pthread_mutex_lock(&gDebuggerNotificationLock);
     _thread_created_hook(tid);
     pthread_mutex_unlock(&gDebuggerNotificationLock);
 
-    // Let the thread do it's thing
+    // Let the thread run.
     pthread_mutex_unlock(start_mutex);
 
-    *thread_out = (pthread_t)thread;
+    *thread_out = (pthread_t) thread;
     return 0;
 }
 
@@ -593,6 +577,17 @@
         _pthread_internal_remove(thread);
         _pthread_internal_free(thread);
     } else {
+        pthread_mutex_lock(&gThreadListLock);
+
+       /* make sure that the thread struct doesn't have stale pointers to a stack that
+        * will be unmapped after the exit call below.
+        */
+        if (!user_stack) {
+            thread->attr.stack_base = NULL;
+            thread->attr.stack_size = 0;
+            thread->tls = NULL;
+        }
+
        /* the join_count field is used to store the number of threads waiting for
         * the termination of this thread with pthread_join(),
         *
@@ -605,7 +600,6 @@
         * is gone (as well as its TLS area). when another thread calls pthread_join()
         * on it, it will immediately free the thread and return.
         */
-        pthread_mutex_lock(&gThreadListLock);
         thread->return_value = retval;
         if (thread->join_count > 0) {
             pthread_cond_broadcast(&thread->join_cond);
@@ -1958,7 +1952,9 @@
          * similarly, it is possible to have thr->tls == NULL for threads that
          * were just recently created through pthread_create() but whose
          * startup trampoline (__thread_entry) hasn't been run yet by the
-         * scheduler. so check for this too.
+         * scheduler. thr->tls will also be NULL after it's stack has been
+         * unmapped but before the ongoing pthread_join() is finished.
+         * so check for this too.
          */
         if (thr->join_count < 0 || !thr->tls)
             continue;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 268cacf..2bd110c 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -41,12 +41,12 @@
     pthread_cond_t              join_cond;
     int                         join_count;
     void*                       return_value;
-    int                         intern;
+    int                         internal_flags;
     __pthread_cleanup_t*        cleanup_stack;
     void**                      tls;         /* thread-local storage area */
 } pthread_internal_t;
 
-extern void _init_thread(pthread_internal_t * thread, pid_t kernel_id, pthread_attr_t * attr, void * stack_base);
+extern int _init_thread(pthread_internal_t * thread, pid_t kernel_id, pthread_attr_t * attr, void * stack_base);
 void _pthread_internal_add( pthread_internal_t*  thread );
 pthread_internal_t* __get_thread(void);
 
diff --git a/libc/bionic/stubs.c b/libc/bionic/stubs.c
index cc4c04e..1aeb581 100644
--- a/libc/bionic/stubs.c
+++ b/libc/bionic/stubs.c
@@ -25,17 +25,19 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <grp.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <netdb.h>
-#include <mntent.h>
-#include <private/android_filesystem_config.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <errno.h>
+
 #include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <mntent.h>
+#include <netdb.h>
+#include <private/android_filesystem_config.h>
+#include <private/logd.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
 
 static int do_getpw_r(int by_name, const char* name, uid_t uid,
         struct passwd* dst, char* buf, size_t byte_count, struct passwd** result)
@@ -438,65 +440,62 @@
     return app_id_to_group( app_id_from_name(name), state );
 }
 
-
-struct netent* getnetbyname(const char *name)
-{
-    fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__);
-    return NULL;
+static void unimplemented_stub(const char* function) {
+  const char* fmt = "%s(3) is not implemented on Android\n";
+  __libc_android_log_print(ANDROID_LOG_WARN, "libc", fmt, function);
+  fprintf(stderr, fmt, function);
 }
 
-void endpwent(void)
-{
+#define UNIMPLEMENTED unimplemented_stub(__PRETTY_FUNCTION__)
+
+struct netent* getnetbyname(const char* name) {
+  UNIMPLEMENTED;
+  return NULL;
 }
 
-struct mntent* getmntent(FILE* f)
-{
-    fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__);
-    return NULL;
+void endpwent(void) {
+  UNIMPLEMENTED;
 }
 
-char* ttyname(int fd)
-{
-    fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__);
-    return NULL;
+struct mntent* getmntent(FILE* f) {
+  UNIMPLEMENTED;
+  return NULL;
 }
 
-int ttyname_r(int fd, char *buf, size_t buflen)
-{
-    fprintf(stderr, "FIX ME! implement ttyname_r() %s:%d\n", __FILE__, __LINE__);
-    return -ERANGE;
+char* ttyname(int fd) {
+  UNIMPLEMENTED;
+  return NULL;
 }
 
-struct netent *getnetbyaddr(uint32_t net, int type)
-{
-    fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
-    return NULL;
+int ttyname_r(int fd, char* buf, size_t buflen) {
+  UNIMPLEMENTED;
+  return -ERANGE;
 }
 
-struct protoent *getprotobyname(const char *name)
-{
-    fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
-    return NULL;
+struct netent* getnetbyaddr(uint32_t net, int type) {
+  UNIMPLEMENTED;
+  return NULL;
 }
 
-struct protoent *getprotobynumber(int proto)
-{
-    fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
-    return NULL;
+struct protoent* getprotobyname(const char* name) {
+  UNIMPLEMENTED;
+  return NULL;
 }
 
-char* getusershell(void)
-{
-    fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
-    return NULL;
+struct protoent* getprotobynumber(int proto) {
+  UNIMPLEMENTED;
+  return NULL;
 }
 
-void setusershell(void)
-{
-    fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
+char* getusershell(void) {
+  UNIMPLEMENTED;
+  return NULL;
 }
 
-void endusershell(void)
-{
-    fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
+void setusershell(void) {
+  UNIMPLEMENTED;
+}
+
+void endusershell(void) {
+  UNIMPLEMENTED;
 }
diff --git a/libc/bionic/system_properties.c b/libc/bionic/system_properties.c
index 0f4e70c..caa5ca6 100644
--- a/libc/bionic/system_properties.c
+++ b/libc/bionic/system_properties.c
@@ -176,7 +176,7 @@
     addr.sun_family = AF_LOCAL;
     alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
 
-    if(TEMP_FAILURE_RETRY(connect(s, (struct sockaddr *) &addr, alen) < 0)) {
+    if(TEMP_FAILURE_RETRY(connect(s, (struct sockaddr *) &addr, alen)) < 0) {
         close(s);
         return result;
     }
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 7219dd7..77c92be 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -49,6 +49,69 @@
 extern int  fcntl(int   fd, int   command, ...);
 extern int  creat(const char*  path, mode_t  mode);
 
+#if defined(__BIONIC_FORTIFY_INLINE)
+
+# if !defined(__clang__)
+/*
+ * Clang doesn't have support for __builtin_va_arg_pack()
+ * and __builtin_va_arg_pack_len()
+ *
+ * http://clang.llvm.org/docs/UsersManual.html#c_unimpl_gcc
+ */
+
+extern void __creat_error()
+    __attribute__((__error__ ("called with O_CREAT, but missing mode")));
+extern void __too_many_args_error()
+    __attribute__((__error__ ("too many arguments")));
+extern int __open_real(const char *pathname, int flags, ...)
+    __asm__(__USER_LABEL_PREFIX__ "open");
+extern int __open_2(const char *, int);
+
+__BIONIC_FORTIFY_INLINE
+int open(const char *pathname, int flags, ...) {
+    if (__builtin_constant_p(flags)) {
+        if ((flags & O_CREAT) && __builtin_va_arg_pack_len() == 0) {
+            __creat_error();  // compile time error
+        }
+    }
+
+    if (__builtin_va_arg_pack_len() > 1) {
+        __too_many_args_error();  // compile time error
+    }
+
+    if ((__builtin_va_arg_pack_len() == 0) && !__builtin_constant_p(flags)) {
+        return __open_2(pathname, flags);
+    }
+
+    return __open_real(pathname, flags, __builtin_va_arg_pack());
+}
+
+extern int __openat_2(int, const char *, int);
+extern int __openat_real(int dirfd, const char *pathname, int flags, ...)
+    __asm__(__USER_LABEL_PREFIX__ "openat");
+
+__BIONIC_FORTIFY_INLINE
+int openat(int dirfd, const char *pathname, int flags, ...) {
+    if (__builtin_constant_p(flags)) {
+        if ((flags & O_CREAT) && __builtin_va_arg_pack_len() == 0) {
+            __creat_error();  // compile time error
+        }
+    }
+
+    if (__builtin_va_arg_pack_len() > 1) {
+        __too_many_args_error();  // compile time error
+    }
+
+    if ((__builtin_va_arg_pack_len() == 0) && !__builtin_constant_p(flags)) {
+        return __openat_2(dirfd, pathname, flags);
+    }
+
+    return __openat_real(dirfd, pathname, flags, __builtin_va_arg_pack());
+}
+
+#endif /* !defined(__clang__) */
+#endif /* defined(__BIONIC_FORTIFY_INLINE) */
+
 __END_DECLS
 
 #endif /* _FCNTL_H */
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 1de8ea6..d691a8f 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -90,6 +90,7 @@
 #endif
 
 #ifndef PAGESIZE
+#include <asm/page.h>
 #define  PAGESIZE  PAGE_SIZE
 #endif
 
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index a864286..bcea672 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -35,7 +35,7 @@
 
 extern __mallocfunc void*  malloc(size_t);
 extern __mallocfunc void*  calloc(size_t, size_t);
-extern __mallocfunc void*  realloc(void *, size_t);
+extern void*  realloc(void *, size_t);
 extern                void   free(void *);
 
 extern void*   memalign(size_t  alignment, size_t  bytesize);
diff --git a/libc/include/net/if_dl.h b/libc/include/net/if_dl.h
deleted file mode 100644
index 1f0c080..0000000
--- a/libc/include/net/if_dl.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*	$NetBSD: if_dl.h,v 1.18 2005/12/11 23:05:24 thorpej Exp $	*/
-
-/*
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)if_dl.h	8.1 (Berkeley) 6/10/93
- */
-
-/*
- * A Link-Level Sockaddr may specify the interface in one of two
- * ways: either by means of a system-provided index number (computed
- * anew and possibly differently on every reboot), or by a human-readable
- * string such as "il0" (for managerial convenience).
- *
- * Census taking actions, such as something akin to SIOCGCONF would return
- * both the index and the human name.
- *
- * High volume transactions (such as giving a link-level ``from'' address
- * in a recvfrom or recvmsg call) may be likely only to provide the indexed
- * form, (which requires fewer copy operations and less space).
- *
- * The form and interpretation  of the link-level address is purely a matter
- * of convention between the device driver and its consumers; however, it is
- * expected that all drivers for an interface of a given if_type will agree.
- */
-
-#ifndef _NET_IF_DL_H_
-#define _NET_IF_DL_H_
-
-#include <sys/socket.h>
-
-/*
- * Structure of a Link-Level sockaddr:
- */
-struct sockaddr_dl {
-	u_char	    sdl_len;	/* Total length of sockaddr */
-	sa_family_t sdl_family;	/* AF_LINK */
-	u_int16_t   sdl_index;	/* if != 0, system given index for interface */
-	u_char	    sdl_type;	/* interface type */
-	u_char	    sdl_nlen;	/* interface name length, no trailing 0 reqd. */
-	u_char	    sdl_alen;	/* link level address length */
-	u_char	    sdl_slen;	/* link layer selector length */
-	char	    sdl_data[12]; /* minimum work area, can be larger;
-				     contains both if name and ll address */
-};
-
-/* We do arithmetic directly with these, so keep them char instead of void */
-#define LLADDR(s) ((char *)((s)->sdl_data + (s)->sdl_nlen))
-#define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
-
-#ifndef _KERNEL
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-void	link_addr(const char *, struct sockaddr_dl *);
-char	*link_ntoa(const struct sockaddr_dl *);
-__END_DECLS
-
-#endif /* !_KERNEL */
-
-#endif /* !_NET_IF_DL_H_ */
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 8d3d5d7..453cf0b 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -231,12 +231,16 @@
 int	 fgetpos(FILE *, fpos_t *);
 char	*fgets(char *, int, FILE *);
 FILE	*fopen(const char *, const char *);
-int	 fprintf(FILE *, const char *, ...);
+int	 fprintf(FILE *, const char *, ...)
+		__attribute__((__format__ (printf, 2, 3)))
+		__attribute__((__nonnull__ (2)));
 int	 fputc(int, FILE *);
 int	 fputs(const char *, FILE *);
 size_t	 fread(void *, size_t, size_t, FILE *);
 FILE	*freopen(const char *, const char *, FILE *);
-int	 fscanf(FILE *, const char *, ...);
+int	 fscanf(FILE *, const char *, ...)
+		__attribute__ ((__format__ (scanf, 2, 3)))
+		__attribute__ ((__nonnull__ (2)));
 int	 fseek(FILE *, long, int);
 int	 fseeko(FILE *, off_t, int);
 int	 fsetpos(FILE *, const fpos_t *);
@@ -253,24 +257,38 @@
 extern char *sys_errlist[];
 #endif
 void	 perror(const char *);
-int	 printf(const char *, ...);
+int	 printf(const char *, ...)
+		__attribute__((__format__ (printf, 1, 2)))
+		__attribute__((__nonnull__ (1)));
 int	 putc(int, FILE *);
 int	 putchar(int);
 int	 puts(const char *);
 int	 remove(const char *);
 int	 rename(const char *, const char *);
 void	 rewind(FILE *);
-int	 scanf(const char *, ...);
+int	 scanf(const char *, ...)
+		__attribute__ ((__format__ (scanf, 1, 2)))
+		__attribute__ ((__nonnull__ (1)));
 void	 setbuf(FILE *, char *);
 int	 setvbuf(FILE *, char *, int, size_t);
-int	 sprintf(char *, const char *, ...);
-int	 sscanf(const char *, const char *, ...);
+int	 sprintf(char *, const char *, ...)
+		__attribute__((__format__ (printf, 2, 3)))
+		__attribute__((__nonnull__ (2)));
+int	 sscanf(const char *, const char *, ...)
+		__attribute__ ((__format__ (scanf, 2, 3)))
+		__attribute__ ((__nonnull__ (2)));
 FILE	*tmpfile(void);
 char	*tmpnam(char *);
 int	 ungetc(int, FILE *);
-int	 vfprintf(FILE *, const char *, __va_list);
-int	 vprintf(const char *, __va_list);
-int	 vsprintf(char *, const char *, __va_list);
+int	 vfprintf(FILE *, const char *, __va_list)
+		__attribute__((__format__ (printf, 2, 0)))
+		__attribute__((__nonnull__ (2)));
+int	 vprintf(const char *, __va_list)
+		__attribute__((__format__ (printf, 1, 0)))
+		__attribute__((__nonnull__ (1)));
+int	 vsprintf(char *, const char *, __va_list)
+		__attribute__((__format__ (printf, 2, 0)))
+		__attribute__((__nonnull__ (2)));
 
 #if __ISO_C_VISIBLE >= 1999 || __BSD_VISIBLE
 int	 snprintf(char *, size_t, const char *, ...)
@@ -453,9 +471,101 @@
  * #define fdprintf dprintf for compatibility
  */
 __BEGIN_DECLS
-int fdprintf(int, const char*, ...);
-int vfdprintf(int, const char*, __va_list);
+int fdprintf(int, const char*, ...)
+		__attribute__((__format__ (printf, 2, 3)))
+		__attribute__((__nonnull__ (2)));
+int vfdprintf(int, const char*, __va_list)
+		__attribute__((__format__ (printf, 2, 0)))
+		__attribute__((__nonnull__ (2)));
 __END_DECLS
 #endif /* _GNU_SOURCE */
 
+#if defined(__BIONIC_FORTIFY_INLINE)
+
+__BIONIC_FORTIFY_INLINE
+__attribute__((__format__ (printf, 3, 0)))
+__attribute__((__nonnull__ (3)))
+int vsnprintf(char *dest, size_t size, const char *format, __va_list ap)
+{
+    return __builtin___vsnprintf_chk(dest, size, 0,
+        __builtin_object_size(dest, 0), format, ap);
+}
+
+__BIONIC_FORTIFY_INLINE
+__attribute__((__format__ (printf, 2, 0)))
+__attribute__((__nonnull__ (2)))
+int vsprintf(char *dest, const char *format, __va_list ap)
+{
+    return __builtin___vsprintf_chk(dest, 0,
+        __builtin_object_size(dest, 0), format, ap);
+}
+
+
+# if !defined(__clang__)
+/*
+ * Clang doesn't have support for __builtin_va_arg_pack()
+ * http://clang.llvm.org/docs/UsersManual.html#c_unimpl_gcc
+ */
+
+__BIONIC_FORTIFY_INLINE
+__attribute__((__format__ (printf, 3, 4)))
+__attribute__((__nonnull__ (3)))
+int snprintf(char *str, size_t size, const char *format, ...)
+{
+    return __builtin___snprintf_chk(str, size, 0,
+        __builtin_object_size(str, 0), format, __builtin_va_arg_pack());
+}
+
+__BIONIC_FORTIFY_INLINE
+__attribute__((__format__ (printf, 2, 3)))
+__attribute__((__nonnull__ (2)))
+int sprintf(char *dest, const char *format, ...)
+{
+    return __builtin___sprintf_chk(dest, 0,
+        __builtin_object_size(dest, 0), format, __builtin_va_arg_pack());
+}
+
+# endif /* !defined(__clang__) */
+
+extern char *__fgets_real(char *, int, FILE *)
+    __asm__(__USER_LABEL_PREFIX__ "fgets");
+extern void __fgets_too_big_error()
+    __attribute__((__error__("fgets called with size bigger than buffer")));
+extern void __fgets_too_small_error()
+    __attribute__((__error__("fgets called with size less than zero")));
+extern char *__fgets_chk(char *, int, FILE *, size_t);
+
+__BIONIC_FORTIFY_INLINE
+char *fgets(char *dest, int size, FILE *stream)
+{
+    size_t bos = __builtin_object_size(dest, 0);
+
+    // Compiler can prove, at compile time, that the passed in size
+    // is always negative. Force a compiler error.
+    if (__builtin_constant_p(size) && (size < 0)) {
+        __fgets_too_small_error();
+    }
+
+    // Compiler doesn't know destination size. Don't call __fgets_chk
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __fgets_real(dest, size, stream);
+    }
+
+    // Compiler can prove, at compile time, that the passed in size
+    // is always <= the actual object size. Don't call __fgets_chk
+    if (__builtin_constant_p(size) && (size <= bos)) {
+        return __fgets_real(dest, size, stream);
+    }
+
+    // Compiler can prove, at compile time, that the passed in size
+    // is always > the actual object size. Force a compiler error.
+    if (__builtin_constant_p(size) && (size > bos)) {
+        __fgets_too_big_error();
+    }
+
+    return __fgets_chk(dest, size, stream, bos);
+}
+
+#endif /* defined(__BIONIC_FORTIFY_INLINE) */
+
 #endif /* _STDIO_H_ */
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index e5caadd..9c0e556 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -74,9 +74,9 @@
     return (float)strtod(nptr, endptr);
 }
 
-extern int atoi(const char *);
-extern long atol(const char *);
-extern long long atoll(const char *);
+extern int atoi(const char *) __purefunc;
+extern long atol(const char *) __purefunc;
+extern long long atoll(const char *) __purefunc;
 
 static __inline__ double atof(const char *nptr)
 {
diff --git a/libc/include/string.h b/libc/include/string.h
index 6e6c8e6..8e472e7 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -85,6 +85,148 @@
 extern int    strcoll(const char *, const char *) __purefunc;
 extern size_t strxfrm(char *, const char *, size_t);
 
+#if defined(__BIONIC_FORTIFY_INLINE)
+
+extern void __memcpy_dest_size_error()
+    __attribute__((__error__("memcpy called with size bigger than destination")));
+extern void __memcpy_src_size_error()
+    __attribute__((__error__("memcpy called with size bigger than source")));
+extern void __memcpy_overlap_error()
+    __attribute__((__error__("memcpy called with overlapping regions")));
+
+__BIONIC_FORTIFY_INLINE
+void *memcpy (void *dest, const void *src, size_t copy_amount) {
+    char *d = (char *) dest;
+    const char *s = (const char *) src;
+    size_t s_len = __builtin_object_size(s, 0);
+    size_t d_len = __builtin_object_size(d, 0);
+
+    if (__builtin_constant_p(copy_amount) && (copy_amount > d_len)) {
+        __memcpy_dest_size_error();
+    }
+
+    if (__builtin_constant_p(copy_amount) && (copy_amount > s_len)) {
+        __memcpy_src_size_error();
+    }
+
+    if (__builtin_constant_p(d - s) && __builtin_constant_p(copy_amount)
+            && (((size_t)(d - s) < copy_amount) || ((size_t)(s - d) < copy_amount))) {
+        __memcpy_overlap_error();
+    }
+
+    return __builtin___memcpy_chk(dest, src, copy_amount, d_len);
+}
+
+__BIONIC_FORTIFY_INLINE
+void *memmove (void *dest, const void *src, size_t len) {
+    return __builtin___memmove_chk(dest, src, len, __builtin_object_size (dest, 0));
+}
+
+__BIONIC_FORTIFY_INLINE
+char *strcpy(char *dest, const char *src) {
+    return __builtin___strcpy_chk(dest, src, __builtin_object_size (dest, 0));
+}
+
+__BIONIC_FORTIFY_INLINE
+char *strncpy(char *dest, const char *src, size_t n) {
+    return __builtin___strncpy_chk(dest, src, n, __builtin_object_size (dest, 0));
+}
+
+__BIONIC_FORTIFY_INLINE
+char *strcat(char *dest, const char *src) {
+    return __builtin___strcat_chk(dest, src, __builtin_object_size (dest, 0));
+}
+
+__BIONIC_FORTIFY_INLINE
+char *strncat(char *dest, const char *src, size_t n) {
+    return __builtin___strncat_chk(dest, src, n, __builtin_object_size (dest, 0));
+}
+
+__BIONIC_FORTIFY_INLINE
+void *memset (void *s, int c, size_t n) {
+    return __builtin___memset_chk(s, c, n, __builtin_object_size (s, 0));
+}
+
+extern size_t __strlcpy_real(char *, const char *, size_t)
+    __asm__(__USER_LABEL_PREFIX__ "strlcpy");
+extern void __strlcpy_error()
+    __attribute__((__error__("strlcpy called with size bigger than buffer")));
+extern size_t __strlcpy_chk(char *, const char *, size_t, size_t);
+
+__BIONIC_FORTIFY_INLINE
+size_t strlcpy(char *dest, const char *src, size_t size) {
+    size_t bos = __builtin_object_size(dest, 0);
+
+    // Compiler doesn't know destination size. Don't call __strlcpy_chk
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __strlcpy_real(dest, src, size);
+    }
+
+    // Compiler can prove, at compile time, that the passed in size
+    // is always <= the actual object size. Don't call __strlcpy_chk
+    if (__builtin_constant_p(size) && (size <= bos)) {
+        return __strlcpy_real(dest, src, size);
+    }
+
+    // Compiler can prove, at compile time, that the passed in size
+    // is always > the actual object size. Force a compiler error.
+    if (__builtin_constant_p(size) && (size > bos)) {
+        __strlcpy_error();
+    }
+
+    return __strlcpy_chk(dest, src, size, bos);
+}
+
+extern size_t __strlcat_real(char *, const char *, size_t)
+    __asm__(__USER_LABEL_PREFIX__ "strlcat");
+extern void __strlcat_error()
+    __attribute__((__error__("strlcat called with size bigger than buffer")));
+extern size_t __strlcat_chk(char *, const char *, size_t, size_t);
+
+
+__BIONIC_FORTIFY_INLINE
+size_t strlcat(char *dest, const char *src, size_t size) {
+    size_t bos = __builtin_object_size(dest, 0);
+
+    // Compiler doesn't know destination size. Don't call __strlcat_chk
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __strlcat_real(dest, src, size);
+    }
+
+    // Compiler can prove, at compile time, that the passed in size
+    // is always <= the actual object size. Don't call __strlcat_chk
+    if (__builtin_constant_p(size) && (size <= bos)) {
+        return __strlcat_real(dest, src, size);
+    }
+
+    // Compiler can prove, at compile time, that the passed in size
+    // is always > the actual object size. Force a compiler error.
+    if (__builtin_constant_p(size) && (size > bos)) {
+        __strlcat_error();
+    }
+
+    return __strlcat_chk(dest, src, size, bos);
+}
+
+__purefunc extern size_t __strlen_real(const char *)
+    __asm__(__USER_LABEL_PREFIX__ "strlen");
+extern size_t __strlen_chk(const char *, size_t);
+
+__BIONIC_FORTIFY_INLINE
+size_t strlen(const char *s) {
+    size_t bos = __builtin_object_size(s, 0);
+
+    // Compiler doesn't know destination size. Don't call __strlen_chk
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __strlen_real(s);
+    }
+
+    return __strlen_chk(s, bos);
+}
+
+
+#endif /* defined(__BIONIC_FORTIFY_INLINE) */
+
 __END_DECLS
 
 #endif /* _STRING_H_ */
diff --git a/libc/include/strings.h b/libc/include/strings.h
index fee7dc4..db2aa3a 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -51,6 +51,14 @@
 char	*rindex(const char *, int);
 int	 strcasecmp(const char *, const char *);
 int	 strncasecmp(const char *, const char *, size_t);
+
+#if defined(__BIONIC_FORTIFY_INLINE)
+__BIONIC_FORTIFY_INLINE
+void bzero (void *s, size_t n) {
+    __builtin___memset_chk(s, '\0', n, __builtin_object_size (s, 0));
+}
+#endif /* defined(__BIONIC_FORTIFY_INLINE) */
+
 __END_DECLS
 
 #endif /* !defined(_STRINGS_H_) */
diff --git a/libc/include/sys/atomics.h b/libc/include/sys/atomics.h
index 3ada8de..143bc4b 100644
--- a/libc/include/sys/atomics.h
+++ b/libc/include/sys/atomics.h
@@ -47,20 +47,20 @@
 #define __ATOMIC_INLINE__ static __inline__ __attribute__((always_inline))
 
 __ATOMIC_INLINE__ int
-__atomic_cmpxchg(int old, int _new, volatile int *ptr)
+__atomic_cmpxchg(int old_value, int new_value, volatile int* ptr)
 {
     /* We must return 0 on success */
-    return __sync_val_compare_and_swap(ptr, old, _new) != old;
+    return __sync_val_compare_and_swap(ptr, old_value, new_value) != old_value;
 }
 
 __ATOMIC_INLINE__ int
-__atomic_swap(int _new, volatile int *ptr)
+__atomic_swap(int new_value, volatile int *ptr)
 {
-    int prev;
+    int old_value;
     do {
-        prev = *ptr;
-    } while (__sync_val_compare_and_swap(ptr, prev, _new) != prev);
-    return prev;
+        old_value = *ptr;
+    } while (__sync_val_compare_and_swap(ptr, old_value, new_value) != old_value);
+    return old_value;
 }
 
 __ATOMIC_INLINE__ int
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 71b419c..987a5e3 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -501,4 +501,13 @@
 #define  __BIONIC__   1
 #include <android/api-level.h>
 
+#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
+#define __BIONIC_FORTIFY_INLINE \
+    extern inline \
+    __attribute__ ((always_inline)) \
+    __attribute__ ((gnu_inline)) \
+    __attribute__ ((artificial))
+#define __BIONIC_FORTIFY_UNKNOWN_SIZE ((size_t) -1)
+#endif
+
 #endif /* !_SYS_CDEFS_H_ */
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index d09e955..c8a654c 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -1,17 +1,94 @@
 /* auto-generated by gensyscalls.py, do not touch */
 #ifndef _BIONIC_LINUX_SYSCALLS_H_
+#define _BIONIC_LINUX_SYSCALLS_H_
 
-#if !defined __ASM_ARM_UNISTD_H && !defined __ASM_I386_UNISTD_H
+#if !defined __ASM_ARM_UNISTD_H && !defined __ASM_I386_UNISTD_H && !defined __ASM_MIPS_UNISTD_H
 #if defined __arm__ && !defined __ARM_EABI__ && !defined __thumb__
-  #  define __NR_SYSCALL_BASE  0x900000
-  #else
-  #  define  __NR_SYSCALL_BASE  0
-  #endif
+  #  define __NR_SYSCALL_BASE 0x900000
+#elif defined(__mips__)
+  #  define __NR_SYSCALL_BASE 4000
+#else
+  #  define __NR_SYSCALL_BASE 0
+#endif
 
 #define __NR_exit                         (__NR_SYSCALL_BASE + 1)
 #define __NR_fork                         (__NR_SYSCALL_BASE + 2)
-#define __NR_clone                        (__NR_SYSCALL_BASE + 120)
+#define __NR_read                         (__NR_SYSCALL_BASE + 3)
+#define __NR_write                        (__NR_SYSCALL_BASE + 4)
+#define __NR_open                         (__NR_SYSCALL_BASE + 5)
+#define __NR_close                        (__NR_SYSCALL_BASE + 6)
+#define __NR_link                         (__NR_SYSCALL_BASE + 9)
+#define __NR_unlink                       (__NR_SYSCALL_BASE + 10)
 #define __NR_execve                       (__NR_SYSCALL_BASE + 11)
+#define __NR_chdir                        (__NR_SYSCALL_BASE + 12)
+#define __NR_mknod                        (__NR_SYSCALL_BASE + 14)
+#define __NR_chmod                        (__NR_SYSCALL_BASE + 15)
+#define __NR_lseek                        (__NR_SYSCALL_BASE + 19)
+#define __NR_getpid                       (__NR_SYSCALL_BASE + 20)
+#define __NR_mount                        (__NR_SYSCALL_BASE + 21)
+#define __NR_ptrace                       (__NR_SYSCALL_BASE + 26)
+#define __NR_pause                        (__NR_SYSCALL_BASE + 29)
+#define __NR_access                       (__NR_SYSCALL_BASE + 33)
+#define __NR_sync                         (__NR_SYSCALL_BASE + 36)
+#define __NR_rename                       (__NR_SYSCALL_BASE + 38)
+#define __NR_mkdir                        (__NR_SYSCALL_BASE + 39)
+#define __NR_rmdir                        (__NR_SYSCALL_BASE + 40)
+#define __NR_dup                          (__NR_SYSCALL_BASE + 41)
+#define __NR_times                        (__NR_SYSCALL_BASE + 43)
+#define __NR_brk                          (__NR_SYSCALL_BASE + 45)
+#define __NR_acct                         (__NR_SYSCALL_BASE + 51)
+#define __NR_umount2                      (__NR_SYSCALL_BASE + 52)
+#define __NR_ioctl                        (__NR_SYSCALL_BASE + 54)
+#define __NR_fcntl                        (__NR_SYSCALL_BASE + 55)
+#define __NR_setpgid                      (__NR_SYSCALL_BASE + 57)
+#define __NR_umask                        (__NR_SYSCALL_BASE + 60)
+#define __NR_chroot                       (__NR_SYSCALL_BASE + 61)
+#define __NR_dup2                         (__NR_SYSCALL_BASE + 63)
+#define __NR_getppid                      (__NR_SYSCALL_BASE + 64)
+#define __NR_setsid                       (__NR_SYSCALL_BASE + 66)
+#define __NR_sigaction                    (__NR_SYSCALL_BASE + 67)
+#define __NR_sigsuspend                   (__NR_SYSCALL_BASE + 72)
+#define __NR_sigpending                   (__NR_SYSCALL_BASE + 73)
+#define __NR_setrlimit                    (__NR_SYSCALL_BASE + 75)
+#define __NR_getrusage                    (__NR_SYSCALL_BASE + 77)
+#define __NR_gettimeofday                 (__NR_SYSCALL_BASE + 78)
+#define __NR_settimeofday                 (__NR_SYSCALL_BASE + 79)
+#define __NR_symlink                      (__NR_SYSCALL_BASE + 83)
+#define __NR_readlink                     (__NR_SYSCALL_BASE + 85)
+#define __NR_reboot                       (__NR_SYSCALL_BASE + 88)
+#define __NR_munmap                       (__NR_SYSCALL_BASE + 91)
+#define __NR_truncate                     (__NR_SYSCALL_BASE + 92)
+#define __NR_ftruncate                    (__NR_SYSCALL_BASE + 93)
+#define __NR_fchmod                       (__NR_SYSCALL_BASE + 94)
+#define __NR_getpriority                  (__NR_SYSCALL_BASE + 96)
+#define __NR_setpriority                  (__NR_SYSCALL_BASE + 97)
+#define __NR_syslog                       (__NR_SYSCALL_BASE + 103)
+#define __NR_syslog                       (__NR_SYSCALL_BASE + 103)
+#define __NR_setitimer                    (__NR_SYSCALL_BASE + 104)
+#define __NR_getitimer                    (__NR_SYSCALL_BASE + 105)
+#define __NR_wait4                        (__NR_SYSCALL_BASE + 114)
+#define __NR_sysinfo                      (__NR_SYSCALL_BASE + 116)
+#define __NR_fsync                        (__NR_SYSCALL_BASE + 118)
+#define __NR_clone                        (__NR_SYSCALL_BASE + 120)
+#define __NR_uname                        (__NR_SYSCALL_BASE + 122)
+#define __NR_mprotect                     (__NR_SYSCALL_BASE + 125)
+#define __NR_sigprocmask                  (__NR_SYSCALL_BASE + 126)
+#define __NR_init_module                  (__NR_SYSCALL_BASE + 128)
+#define __NR_delete_module                (__NR_SYSCALL_BASE + 129)
+#define __NR_getpgid                      (__NR_SYSCALL_BASE + 132)
+#define __NR_fchdir                       (__NR_SYSCALL_BASE + 133)
+#define __NR_personality                  (__NR_SYSCALL_BASE + 136)
+#define __NR__llseek                      (__NR_SYSCALL_BASE + 140)
+#define __NR__newselect                   (__NR_SYSCALL_BASE + 142)
+#define __NR_flock                        (__NR_SYSCALL_BASE + 143)
+#define __NR_msync                        (__NR_SYSCALL_BASE + 144)
+#define __NR_readv                        (__NR_SYSCALL_BASE + 145)
+#define __NR_writev                       (__NR_SYSCALL_BASE + 146)
+#define __NR_perf_event_open              (__NR_SYSCALL_BASE + 364)
+
+#ifdef __arm__
+#define __NR_exit_group                   (__NR_SYSCALL_BASE + 248)
+#define __NR_waitid                       (__NR_SYSCALL_BASE + 280)
 #define __NR_setuid32                     (__NR_SYSCALL_BASE + 213)
 #define __NR_getuid32                     (__NR_SYSCALL_BASE + 199)
 #define __NR_getgid32                     (__NR_SYSCALL_BASE + 200)
@@ -22,88 +99,53 @@
 #define __NR_gettid                       (__NR_SYSCALL_BASE + 224)
 #define __NR_readahead                    (__NR_SYSCALL_BASE + 225)
 #define __NR_getgroups32                  (__NR_SYSCALL_BASE + 205)
-#define __NR_getpgid                      (__NR_SYSCALL_BASE + 132)
-#define __NR_getppid                      (__NR_SYSCALL_BASE + 64)
-#define __NR_setsid                       (__NR_SYSCALL_BASE + 66)
 #define __NR_setgid32                     (__NR_SYSCALL_BASE + 214)
 #define __NR_setreuid32                   (__NR_SYSCALL_BASE + 203)
 #define __NR_setresuid32                  (__NR_SYSCALL_BASE + 208)
 #define __NR_setresgid32                  (__NR_SYSCALL_BASE + 210)
-#define __NR_brk                          (__NR_SYSCALL_BASE + 45)
-#define __NR_ptrace                       (__NR_SYSCALL_BASE + 26)
-#define __NR_getpriority                  (__NR_SYSCALL_BASE + 96)
-#define __NR_setpriority                  (__NR_SYSCALL_BASE + 97)
-#define __NR_setrlimit                    (__NR_SYSCALL_BASE + 75)
 #define __NR_ugetrlimit                   (__NR_SYSCALL_BASE + 191)
-#define __NR_getrusage                    (__NR_SYSCALL_BASE + 77)
 #define __NR_setgroups32                  (__NR_SYSCALL_BASE + 206)
-#define __NR_setpgid                      (__NR_SYSCALL_BASE + 57)
+#define __NR_vfork                        (__NR_SYSCALL_BASE + 190)
 #define __NR_setregid32                   (__NR_SYSCALL_BASE + 204)
-#define __NR_chroot                       (__NR_SYSCALL_BASE + 61)
 #define __NR_prctl                        (__NR_SYSCALL_BASE + 172)
 #define __NR_capget                       (__NR_SYSCALL_BASE + 184)
 #define __NR_capset                       (__NR_SYSCALL_BASE + 185)
 #define __NR_sigaltstack                  (__NR_SYSCALL_BASE + 186)
-#define __NR_acct                         (__NR_SYSCALL_BASE + 51)
-#define __NR_read                         (__NR_SYSCALL_BASE + 3)
-#define __NR_write                        (__NR_SYSCALL_BASE + 4)
 #define __NR_pread64                      (__NR_SYSCALL_BASE + 180)
 #define __NR_pwrite64                     (__NR_SYSCALL_BASE + 181)
-#define __NR_open                         (__NR_SYSCALL_BASE + 5)
-#define __NR_close                        (__NR_SYSCALL_BASE + 6)
-#define __NR_lseek                        (__NR_SYSCALL_BASE + 19)
-#define __NR__llseek                      (__NR_SYSCALL_BASE + 140)
-#define __NR_getpid                       (__NR_SYSCALL_BASE + 20)
+#define __NR_openat                       (__NR_SYSCALL_BASE + 322)
 #define __NR_mmap2                        (__NR_SYSCALL_BASE + 192)
-#define __NR_munmap                       (__NR_SYSCALL_BASE + 91)
 #define __NR_mremap                       (__NR_SYSCALL_BASE + 163)
-#define __NR_msync                        (__NR_SYSCALL_BASE + 144)
-#define __NR_mprotect                     (__NR_SYSCALL_BASE + 125)
+#define __NR_madvise                      (__NR_SYSCALL_BASE + 220)
 #define __NR_mlock                        (__NR_SYSCALL_BASE + 150)
 #define __NR_munlock                      (__NR_SYSCALL_BASE + 151)
-#define __NR_ioctl                        (__NR_SYSCALL_BASE + 54)
-#define __NR_readv                        (__NR_SYSCALL_BASE + 145)
-#define __NR_writev                       (__NR_SYSCALL_BASE + 146)
-#define __NR_fcntl                        (__NR_SYSCALL_BASE + 55)
-#define __NR_flock                        (__NR_SYSCALL_BASE + 143)
-#define __NR_fchmod                       (__NR_SYSCALL_BASE + 94)
-#define __NR_dup                          (__NR_SYSCALL_BASE + 41)
+#define __NR_mincore                      (__NR_SYSCALL_BASE + 219)
 #define __NR_pipe                         (__NR_SYSCALL_BASE + 42)
-#define __NR_dup2                         (__NR_SYSCALL_BASE + 63)
-#define __NR__newselect                   (__NR_SYSCALL_BASE + 142)
-#define __NR_ftruncate                    (__NR_SYSCALL_BASE + 93)
+#define __NR_pipe2                        (__NR_SYSCALL_BASE + 359)
 #define __NR_ftruncate64                  (__NR_SYSCALL_BASE + 194)
-#define __NR_fsync                        (__NR_SYSCALL_BASE + 118)
+#define __NR_getdents64                   (__NR_SYSCALL_BASE + 217)
 #define __NR_fdatasync                    (__NR_SYSCALL_BASE + 148)
 #define __NR_fchown32                     (__NR_SYSCALL_BASE + 207)
-#define __NR_sync                         (__NR_SYSCALL_BASE + 36)
 #define __NR_fcntl64                      (__NR_SYSCALL_BASE + 221)
+#define __NR_fstatfs64                    (__NR_SYSCALL_BASE + 267)
 #define __NR_sendfile                     (__NR_SYSCALL_BASE + 187)
+#define __NR_fstatat64                    (__NR_SYSCALL_BASE + 327)
+#define __NR_mkdirat                      (__NR_SYSCALL_BASE + 323)
+#define __NR_fchownat                     (__NR_SYSCALL_BASE + 325)
+#define __NR_fchmodat                     (__NR_SYSCALL_BASE + 333)
+#define __NR_renameat                     (__NR_SYSCALL_BASE + 329)
 #define __NR_fsetxattr                    (__NR_SYSCALL_BASE + 228)
 #define __NR_fgetxattr                    (__NR_SYSCALL_BASE + 231)
 #define __NR_flistxattr                   (__NR_SYSCALL_BASE + 234)
 #define __NR_fremovexattr                 (__NR_SYSCALL_BASE + 237)
-#define __NR_link                         (__NR_SYSCALL_BASE + 9)
-#define __NR_unlink                       (__NR_SYSCALL_BASE + 10)
-#define __NR_chdir                        (__NR_SYSCALL_BASE + 12)
-#define __NR_mknod                        (__NR_SYSCALL_BASE + 14)
-#define __NR_chmod                        (__NR_SYSCALL_BASE + 15)
+#define __NR_unlinkat                     (__NR_SYSCALL_BASE + 328)
 #define __NR_chown32                      (__NR_SYSCALL_BASE + 212)
 #define __NR_lchown32                     (__NR_SYSCALL_BASE + 198)
-#define __NR_mount                        (__NR_SYSCALL_BASE + 21)
-#define __NR_umount2                      (__NR_SYSCALL_BASE + 52)
 #define __NR_fstat64                      (__NR_SYSCALL_BASE + 197)
 #define __NR_stat64                       (__NR_SYSCALL_BASE + 195)
 #define __NR_lstat64                      (__NR_SYSCALL_BASE + 196)
-#define __NR_mkdir                        (__NR_SYSCALL_BASE + 39)
-#define __NR_readlink                     (__NR_SYSCALL_BASE + 85)
-#define __NR_rmdir                        (__NR_SYSCALL_BASE + 40)
-#define __NR_rename                       (__NR_SYSCALL_BASE + 38)
 #define __NR_getcwd                       (__NR_SYSCALL_BASE + 183)
-#define __NR_access                       (__NR_SYSCALL_BASE + 33)
-#define __NR_symlink                      (__NR_SYSCALL_BASE + 83)
-#define __NR_fchdir                       (__NR_SYSCALL_BASE + 133)
-#define __NR_truncate                     (__NR_SYSCALL_BASE + 92)
+#define __NR_faccessat                    (__NR_SYSCALL_BASE + 334)
 #define __NR_setxattr                     (__NR_SYSCALL_BASE + 226)
 #define __NR_lsetxattr                    (__NR_SYSCALL_BASE + 227)
 #define __NR_getxattr                     (__NR_SYSCALL_BASE + 229)
@@ -112,62 +154,8 @@
 #define __NR_llistxattr                   (__NR_SYSCALL_BASE + 233)
 #define __NR_removexattr                  (__NR_SYSCALL_BASE + 235)
 #define __NR_lremovexattr                 (__NR_SYSCALL_BASE + 236)
-#define __NR_pause                        (__NR_SYSCALL_BASE + 29)
-#define __NR_gettimeofday                 (__NR_SYSCALL_BASE + 78)
-#define __NR_settimeofday                 (__NR_SYSCALL_BASE + 79)
-#define __NR_times                        (__NR_SYSCALL_BASE + 43)
-#define __NR_nanosleep                    (__NR_SYSCALL_BASE + 162)
-#define __NR_getitimer                    (__NR_SYSCALL_BASE + 105)
-#define __NR_setitimer                    (__NR_SYSCALL_BASE + 104)
-#define __NR_sigaction                    (__NR_SYSCALL_BASE + 67)
-#define __NR_sigprocmask                  (__NR_SYSCALL_BASE + 126)
-#define __NR_sigsuspend                   (__NR_SYSCALL_BASE + 72)
-#define __NR_rt_sigaction                 (__NR_SYSCALL_BASE + 174)
-#define __NR_rt_sigprocmask               (__NR_SYSCALL_BASE + 175)
-#define __NR_rt_sigtimedwait              (__NR_SYSCALL_BASE + 177)
-#define __NR_sigpending                   (__NR_SYSCALL_BASE + 73)
-#define __NR_sched_setscheduler           (__NR_SYSCALL_BASE + 156)
-#define __NR_sched_getscheduler           (__NR_SYSCALL_BASE + 157)
-#define __NR_sched_yield                  (__NR_SYSCALL_BASE + 158)
-#define __NR_sched_setparam               (__NR_SYSCALL_BASE + 154)
-#define __NR_sched_getparam               (__NR_SYSCALL_BASE + 155)
-#define __NR_sched_get_priority_max       (__NR_SYSCALL_BASE + 159)
-#define __NR_sched_get_priority_min       (__NR_SYSCALL_BASE + 160)
-#define __NR_sched_rr_get_interval        (__NR_SYSCALL_BASE + 161)
-#define __NR_sched_setaffinity            (__NR_SYSCALL_BASE + 241)
-#define __NR_sched_getaffinity            (__NR_SYSCALL_BASE + 242)
-#define __NR_uname                        (__NR_SYSCALL_BASE + 122)
-#define __NR_wait4                        (__NR_SYSCALL_BASE + 114)
-#define __NR_umask                        (__NR_SYSCALL_BASE + 60)
-#define __NR_reboot                       (__NR_SYSCALL_BASE + 88)
-#define __NR_syslog                       (__NR_SYSCALL_BASE + 103)
-#define __NR_init_module                  (__NR_SYSCALL_BASE + 128)
-#define __NR_delete_module                (__NR_SYSCALL_BASE + 129)
-#define __NR_syslog                       (__NR_SYSCALL_BASE + 103)
-#define __NR_sysinfo                      (__NR_SYSCALL_BASE + 116)
-#define __NR_personality                  (__NR_SYSCALL_BASE + 136)
-#define __NR_perf_event_open              (__NR_SYSCALL_BASE + 364)
-#define __NR_futex                        (__NR_SYSCALL_BASE + 240)
-#define __NR_poll                         (__NR_SYSCALL_BASE + 168)
-
-#ifdef __arm__
-#define __NR_exit_group                   (__NR_SYSCALL_BASE + 248)
-#define __NR_waitid                       (__NR_SYSCALL_BASE + 280)
-#define __NR_vfork                        (__NR_SYSCALL_BASE + 190)
-#define __NR_openat                       (__NR_SYSCALL_BASE + 322)
-#define __NR_madvise                      (__NR_SYSCALL_BASE + 220)
-#define __NR_mincore                      (__NR_SYSCALL_BASE + 219)
-#define __NR_pipe2                        (__NR_SYSCALL_BASE + 359)
-#define __NR_getdents64                   (__NR_SYSCALL_BASE + 217)
-#define __NR_fstatfs64                    (__NR_SYSCALL_BASE + 267)
-#define __NR_fstatat64                    (__NR_SYSCALL_BASE + 327)
-#define __NR_mkdirat                      (__NR_SYSCALL_BASE + 323)
-#define __NR_fchownat                     (__NR_SYSCALL_BASE + 325)
-#define __NR_fchmodat                     (__NR_SYSCALL_BASE + 333)
-#define __NR_renameat                     (__NR_SYSCALL_BASE + 329)
-#define __NR_unlinkat                     (__NR_SYSCALL_BASE + 328)
-#define __NR_faccessat                    (__NR_SYSCALL_BASE + 334)
 #define __NR_statfs64                     (__NR_SYSCALL_BASE + 266)
+#define __NR_nanosleep                    (__NR_SYSCALL_BASE + 162)
 #define __NR_clock_gettime                (__NR_SYSCALL_BASE + 263)
 #define __NR_clock_settime                (__NR_SYSCALL_BASE + 262)
 #define __NR_clock_getres                 (__NR_SYSCALL_BASE + 264)
@@ -179,6 +167,9 @@
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 261)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 269)
 #define __NR_utimensat                    (__NR_SYSCALL_BASE + 348)
+#define __NR_rt_sigaction                 (__NR_SYSCALL_BASE + 174)
+#define __NR_rt_sigprocmask               (__NR_SYSCALL_BASE + 175)
+#define __NR_rt_sigtimedwait              (__NR_SYSCALL_BASE + 177)
 #define __NR_socket                       (__NR_SYSCALL_BASE + 281)
 #define __NR_socketpair                   (__NR_SYSCALL_BASE + 288)
 #define __NR_bind                         (__NR_SYSCALL_BASE + 282)
@@ -194,64 +185,271 @@
 #define __NR_getsockopt                   (__NR_SYSCALL_BASE + 295)
 #define __NR_sendmsg                      (__NR_SYSCALL_BASE + 296)
 #define __NR_recvmsg                      (__NR_SYSCALL_BASE + 297)
+#define __NR_sched_setscheduler           (__NR_SYSCALL_BASE + 156)
+#define __NR_sched_getscheduler           (__NR_SYSCALL_BASE + 157)
+#define __NR_sched_yield                  (__NR_SYSCALL_BASE + 158)
+#define __NR_sched_setparam               (__NR_SYSCALL_BASE + 154)
+#define __NR_sched_getparam               (__NR_SYSCALL_BASE + 155)
+#define __NR_sched_get_priority_max       (__NR_SYSCALL_BASE + 159)
+#define __NR_sched_get_priority_min       (__NR_SYSCALL_BASE + 160)
+#define __NR_sched_rr_get_interval        (__NR_SYSCALL_BASE + 161)
+#define __NR_sched_setaffinity            (__NR_SYSCALL_BASE + 241)
+#define __NR_sched_getaffinity            (__NR_SYSCALL_BASE + 242)
 #define __NR_getcpu                       (__NR_SYSCALL_BASE + 345)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 314)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 315)
+#define __NR_futex                        (__NR_SYSCALL_BASE + 240)
 #define __NR_epoll_create                 (__NR_SYSCALL_BASE + 250)
 #define __NR_epoll_ctl                    (__NR_SYSCALL_BASE + 251)
 #define __NR_epoll_wait                   (__NR_SYSCALL_BASE + 252)
 #define __NR_inotify_init                 (__NR_SYSCALL_BASE + 316)
 #define __NR_inotify_add_watch            (__NR_SYSCALL_BASE + 317)
 #define __NR_inotify_rm_watch             (__NR_SYSCALL_BASE + 318)
+#define __NR_poll                         (__NR_SYSCALL_BASE + 168)
 #define __NR_eventfd2                     (__NR_SYSCALL_BASE + 356)
 #define __NR_ARM_set_tls                  (__NR_SYSCALL_BASE + 983045)
 #define __NR_ARM_cacheflush               (__NR_SYSCALL_BASE + 983042)
 #endif
 
 #ifdef __i386__
-#define __NR_exit_group                   (__NR_SYSCALL_BASE + 252)
 #define __NR_waitpid                      (__NR_SYSCALL_BASE + 7)
-#define __NR_waitid                       (__NR_SYSCALL_BASE + 284)
 #define __NR_kill                         (__NR_SYSCALL_BASE + 37)
-#define __NR_tkill                        (__NR_SYSCALL_BASE + 238)
-#define __NR_tgkill                       (__NR_SYSCALL_BASE + 270)
-#define __NR_set_thread_area              (__NR_SYSCALL_BASE + 243)
-#define __NR_openat                       (__NR_SYSCALL_BASE + 295)
-#define __NR_madvise                      (__NR_SYSCALL_BASE + 219)
+#define __NR_pipe                         (__NR_SYSCALL_BASE + 42)
+#define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
+#define __NR_fdatasync                    (__NR_SYSCALL_BASE + 148)
+#define __NR_mlock                        (__NR_SYSCALL_BASE + 150)
+#define __NR_munlock                      (__NR_SYSCALL_BASE + 151)
+#define __NR_sched_setparam               (__NR_SYSCALL_BASE + 154)
+#define __NR_sched_getparam               (__NR_SYSCALL_BASE + 155)
+#define __NR_sched_setscheduler           (__NR_SYSCALL_BASE + 156)
+#define __NR_sched_getscheduler           (__NR_SYSCALL_BASE + 157)
+#define __NR_sched_yield                  (__NR_SYSCALL_BASE + 158)
+#define __NR_sched_get_priority_max       (__NR_SYSCALL_BASE + 159)
+#define __NR_sched_get_priority_min       (__NR_SYSCALL_BASE + 160)
+#define __NR_sched_rr_get_interval        (__NR_SYSCALL_BASE + 161)
+#define __NR_nanosleep                    (__NR_SYSCALL_BASE + 162)
+#define __NR_mremap                       (__NR_SYSCALL_BASE + 163)
+#define __NR_poll                         (__NR_SYSCALL_BASE + 168)
+#define __NR_prctl                        (__NR_SYSCALL_BASE + 172)
+#define __NR_rt_sigaction                 (__NR_SYSCALL_BASE + 174)
+#define __NR_rt_sigprocmask               (__NR_SYSCALL_BASE + 175)
+#define __NR_rt_sigtimedwait              (__NR_SYSCALL_BASE + 177)
+#define __NR_pread64                      (__NR_SYSCALL_BASE + 180)
+#define __NR_pwrite64                     (__NR_SYSCALL_BASE + 181)
+#define __NR_getcwd                       (__NR_SYSCALL_BASE + 183)
+#define __NR_capget                       (__NR_SYSCALL_BASE + 184)
+#define __NR_capset                       (__NR_SYSCALL_BASE + 185)
+#define __NR_sigaltstack                  (__NR_SYSCALL_BASE + 186)
+#define __NR_sendfile                     (__NR_SYSCALL_BASE + 187)
+#define __NR_ugetrlimit                   (__NR_SYSCALL_BASE + 191)
+#define __NR_mmap2                        (__NR_SYSCALL_BASE + 192)
+#define __NR_ftruncate64                  (__NR_SYSCALL_BASE + 194)
+#define __NR_stat64                       (__NR_SYSCALL_BASE + 195)
+#define __NR_lstat64                      (__NR_SYSCALL_BASE + 196)
+#define __NR_fstat64                      (__NR_SYSCALL_BASE + 197)
+#define __NR_lchown32                     (__NR_SYSCALL_BASE + 198)
+#define __NR_getuid32                     (__NR_SYSCALL_BASE + 199)
+#define __NR_getgid32                     (__NR_SYSCALL_BASE + 200)
+#define __NR_geteuid32                    (__NR_SYSCALL_BASE + 201)
+#define __NR_getegid32                    (__NR_SYSCALL_BASE + 202)
+#define __NR_setreuid32                   (__NR_SYSCALL_BASE + 203)
+#define __NR_setregid32                   (__NR_SYSCALL_BASE + 204)
+#define __NR_getgroups32                  (__NR_SYSCALL_BASE + 205)
+#define __NR_setgroups32                  (__NR_SYSCALL_BASE + 206)
+#define __NR_fchown32                     (__NR_SYSCALL_BASE + 207)
+#define __NR_setresuid32                  (__NR_SYSCALL_BASE + 208)
+#define __NR_getresuid32                  (__NR_SYSCALL_BASE + 209)
+#define __NR_setresgid32                  (__NR_SYSCALL_BASE + 210)
+#define __NR_getresgid32                  (__NR_SYSCALL_BASE + 211)
+#define __NR_chown32                      (__NR_SYSCALL_BASE + 212)
+#define __NR_setuid32                     (__NR_SYSCALL_BASE + 213)
+#define __NR_setgid32                     (__NR_SYSCALL_BASE + 214)
 #define __NR_mincore                      (__NR_SYSCALL_BASE + 218)
-#define __NR_pipe2                        (__NR_SYSCALL_BASE + 331)
+#define __NR_madvise                      (__NR_SYSCALL_BASE + 219)
 #define __NR_getdents64                   (__NR_SYSCALL_BASE + 220)
-#define __NR_fstatfs64                    (__NR_SYSCALL_BASE + 269)
-#define __NR_fstatat64                    (__NR_SYSCALL_BASE + 300)
-#define __NR_mkdirat                      (__NR_SYSCALL_BASE + 296)
-#define __NR_fchownat                     (__NR_SYSCALL_BASE + 298)
-#define __NR_fchmodat                     (__NR_SYSCALL_BASE + 306)
-#define __NR_renameat                     (__NR_SYSCALL_BASE + 302)
-#define __NR_unlinkat                     (__NR_SYSCALL_BASE + 301)
-#define __NR_faccessat                    (__NR_SYSCALL_BASE + 307)
-#define __NR_statfs64                     (__NR_SYSCALL_BASE + 268)
-#define __NR_clock_gettime                (__NR_SYSCALL_BASE + 265)
-#define __NR_clock_settime                (__NR_SYSCALL_BASE + 264)
-#define __NR_clock_getres                 (__NR_SYSCALL_BASE + 266)
-#define __NR_clock_nanosleep              (__NR_SYSCALL_BASE + 267)
+#define __NR_fcntl64                      (__NR_SYSCALL_BASE + 221)
+#define __NR_gettid                       (__NR_SYSCALL_BASE + 224)
+#define __NR_readahead                    (__NR_SYSCALL_BASE + 225)
+#define __NR_setxattr                     (__NR_SYSCALL_BASE + 226)
+#define __NR_lsetxattr                    (__NR_SYSCALL_BASE + 227)
+#define __NR_fsetxattr                    (__NR_SYSCALL_BASE + 228)
+#define __NR_getxattr                     (__NR_SYSCALL_BASE + 229)
+#define __NR_lgetxattr                    (__NR_SYSCALL_BASE + 230)
+#define __NR_fgetxattr                    (__NR_SYSCALL_BASE + 231)
+#define __NR_listxattr                    (__NR_SYSCALL_BASE + 232)
+#define __NR_llistxattr                   (__NR_SYSCALL_BASE + 233)
+#define __NR_flistxattr                   (__NR_SYSCALL_BASE + 234)
+#define __NR_removexattr                  (__NR_SYSCALL_BASE + 235)
+#define __NR_lremovexattr                 (__NR_SYSCALL_BASE + 236)
+#define __NR_fremovexattr                 (__NR_SYSCALL_BASE + 237)
+#define __NR_tkill                        (__NR_SYSCALL_BASE + 238)
+#define __NR_futex                        (__NR_SYSCALL_BASE + 240)
+#define __NR_sched_setaffinity            (__NR_SYSCALL_BASE + 241)
+#define __NR_sched_getaffinity            (__NR_SYSCALL_BASE + 242)
+#define __NR_set_thread_area              (__NR_SYSCALL_BASE + 243)
+#define __NR_exit_group                   (__NR_SYSCALL_BASE + 252)
+#define __NR_epoll_create                 (__NR_SYSCALL_BASE + 254)
+#define __NR_epoll_ctl                    (__NR_SYSCALL_BASE + 255)
+#define __NR_epoll_wait                   (__NR_SYSCALL_BASE + 256)
 #define __NR_timer_create                 (__NR_SYSCALL_BASE + 259)
 #define __NR_timer_settime                (__NR_SYSCALL_BASE + 260)
 #define __NR_timer_gettime                (__NR_SYSCALL_BASE + 261)
 #define __NR_timer_getoverrun             (__NR_SYSCALL_BASE + 262)
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 263)
+#define __NR_clock_settime                (__NR_SYSCALL_BASE + 264)
+#define __NR_clock_gettime                (__NR_SYSCALL_BASE + 265)
+#define __NR_clock_getres                 (__NR_SYSCALL_BASE + 266)
+#define __NR_clock_nanosleep              (__NR_SYSCALL_BASE + 267)
+#define __NR_statfs64                     (__NR_SYSCALL_BASE + 268)
+#define __NR_fstatfs64                    (__NR_SYSCALL_BASE + 269)
+#define __NR_tgkill                       (__NR_SYSCALL_BASE + 270)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 271)
-#define __NR_utimensat                    (__NR_SYSCALL_BASE + 320)
-#define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
-#define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
+#define __NR_waitid                       (__NR_SYSCALL_BASE + 284)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 289)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 290)
-#define __NR_epoll_create                 (__NR_SYSCALL_BASE + 254)
-#define __NR_epoll_ctl                    (__NR_SYSCALL_BASE + 255)
-#define __NR_epoll_wait                   (__NR_SYSCALL_BASE + 256)
 #define __NR_inotify_init                 (__NR_SYSCALL_BASE + 291)
 #define __NR_inotify_add_watch            (__NR_SYSCALL_BASE + 292)
 #define __NR_inotify_rm_watch             (__NR_SYSCALL_BASE + 293)
+#define __NR_openat                       (__NR_SYSCALL_BASE + 295)
+#define __NR_mkdirat                      (__NR_SYSCALL_BASE + 296)
+#define __NR_fchownat                     (__NR_SYSCALL_BASE + 298)
+#define __NR_fstatat64                    (__NR_SYSCALL_BASE + 300)
+#define __NR_unlinkat                     (__NR_SYSCALL_BASE + 301)
+#define __NR_renameat                     (__NR_SYSCALL_BASE + 302)
+#define __NR_fchmodat                     (__NR_SYSCALL_BASE + 306)
+#define __NR_faccessat                    (__NR_SYSCALL_BASE + 307)
+#define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
+#define __NR_utimensat                    (__NR_SYSCALL_BASE + 320)
 #define __NR_eventfd2                     (__NR_SYSCALL_BASE + 328)
+#define __NR_pipe2                        (__NR_SYSCALL_BASE + 331)
+#endif
+
+#ifdef __mips__
+#define __NR_syscall                      (__NR_SYSCALL_BASE + 0)
+#define __NR_waitpid                      (__NR_SYSCALL_BASE + 7)
+#define __NR_lchown                       (__NR_SYSCALL_BASE + 16)
+#define __NR_setuid                       (__NR_SYSCALL_BASE + 23)
+#define __NR_getuid                       (__NR_SYSCALL_BASE + 24)
+#define __NR_kill                         (__NR_SYSCALL_BASE + 37)
+#define __NR_setgid                       (__NR_SYSCALL_BASE + 46)
+#define __NR_getgid                       (__NR_SYSCALL_BASE + 47)
+#define __NR_geteuid                      (__NR_SYSCALL_BASE + 49)
+#define __NR_getegid                      (__NR_SYSCALL_BASE + 50)
+#define __NR_setreuid                     (__NR_SYSCALL_BASE + 70)
+#define __NR_setregid                     (__NR_SYSCALL_BASE + 71)
+#define __NR_getrlimit                    (__NR_SYSCALL_BASE + 76)
+#define __NR_getgroups                    (__NR_SYSCALL_BASE + 80)
+#define __NR_setgroups                    (__NR_SYSCALL_BASE + 81)
+#define __NR_fchown                       (__NR_SYSCALL_BASE + 95)
+#define __NR_cacheflush                   (__NR_SYSCALL_BASE + 147)
+#define __NR_fdatasync                    (__NR_SYSCALL_BASE + 152)
+#define __NR_mlock                        (__NR_SYSCALL_BASE + 154)
+#define __NR_munlock                      (__NR_SYSCALL_BASE + 155)
+#define __NR_sched_setparam               (__NR_SYSCALL_BASE + 158)
+#define __NR_sched_getparam               (__NR_SYSCALL_BASE + 159)
+#define __NR_sched_setscheduler           (__NR_SYSCALL_BASE + 160)
+#define __NR_sched_getscheduler           (__NR_SYSCALL_BASE + 161)
+#define __NR_sched_yield                  (__NR_SYSCALL_BASE + 162)
+#define __NR_sched_get_priority_max       (__NR_SYSCALL_BASE + 163)
+#define __NR_sched_get_priority_min       (__NR_SYSCALL_BASE + 164)
+#define __NR_sched_rr_get_interval        (__NR_SYSCALL_BASE + 165)
+#define __NR_nanosleep                    (__NR_SYSCALL_BASE + 166)
+#define __NR_mremap                       (__NR_SYSCALL_BASE + 167)
+#define __NR_accept                       (__NR_SYSCALL_BASE + 168)
+#define __NR_bind                         (__NR_SYSCALL_BASE + 169)
+#define __NR_connect                      (__NR_SYSCALL_BASE + 170)
+#define __NR_getpeername                  (__NR_SYSCALL_BASE + 171)
+#define __NR_getsockname                  (__NR_SYSCALL_BASE + 172)
+#define __NR_getsockopt                   (__NR_SYSCALL_BASE + 173)
+#define __NR_listen                       (__NR_SYSCALL_BASE + 174)
+#define __NR_recvfrom                     (__NR_SYSCALL_BASE + 176)
+#define __NR_recvmsg                      (__NR_SYSCALL_BASE + 177)
+#define __NR_sendmsg                      (__NR_SYSCALL_BASE + 179)
+#define __NR_sendto                       (__NR_SYSCALL_BASE + 180)
+#define __NR_setsockopt                   (__NR_SYSCALL_BASE + 181)
+#define __NR_shutdown                     (__NR_SYSCALL_BASE + 182)
+#define __NR_socket                       (__NR_SYSCALL_BASE + 183)
+#define __NR_socketpair                   (__NR_SYSCALL_BASE + 184)
+#define __NR_setresuid                    (__NR_SYSCALL_BASE + 185)
+#define __NR_getresuid                    (__NR_SYSCALL_BASE + 186)
+#define __NR_poll                         (__NR_SYSCALL_BASE + 188)
+#define __NR_setresgid                    (__NR_SYSCALL_BASE + 190)
+#define __NR_getresgid                    (__NR_SYSCALL_BASE + 191)
+#define __NR_prctl                        (__NR_SYSCALL_BASE + 192)
+#define __NR_rt_sigaction                 (__NR_SYSCALL_BASE + 194)
+#define __NR_rt_sigprocmask               (__NR_SYSCALL_BASE + 195)
+#define __NR_rt_sigtimedwait              (__NR_SYSCALL_BASE + 197)
+#define __NR_pread64                      (__NR_SYSCALL_BASE + 200)
+#define __NR_pwrite64                     (__NR_SYSCALL_BASE + 201)
+#define __NR_chown                        (__NR_SYSCALL_BASE + 202)
+#define __NR_getcwd                       (__NR_SYSCALL_BASE + 203)
+#define __NR_capget                       (__NR_SYSCALL_BASE + 204)
+#define __NR_capset                       (__NR_SYSCALL_BASE + 205)
+#define __NR_sigaltstack                  (__NR_SYSCALL_BASE + 206)
+#define __NR_sendfile                     (__NR_SYSCALL_BASE + 207)
+#define __NR_mmap2                        (__NR_SYSCALL_BASE + 210)
+#define __NR_ftruncate64                  (__NR_SYSCALL_BASE + 212)
+#define __NR_stat64                       (__NR_SYSCALL_BASE + 213)
+#define __NR_lstat64                      (__NR_SYSCALL_BASE + 214)
+#define __NR_fstat64                      (__NR_SYSCALL_BASE + 215)
+#define __NR_mincore                      (__NR_SYSCALL_BASE + 217)
+#define __NR_madvise                      (__NR_SYSCALL_BASE + 218)
+#define __NR_getdents64                   (__NR_SYSCALL_BASE + 219)
+#define __NR_fcntl64                      (__NR_SYSCALL_BASE + 220)
+#define __NR_gettid                       (__NR_SYSCALL_BASE + 222)
+#define __NR_readahead                    (__NR_SYSCALL_BASE + 223)
+#define __NR_setxattr                     (__NR_SYSCALL_BASE + 224)
+#define __NR_lsetxattr                    (__NR_SYSCALL_BASE + 225)
+#define __NR_fsetxattr                    (__NR_SYSCALL_BASE + 226)
+#define __NR_getxattr                     (__NR_SYSCALL_BASE + 227)
+#define __NR_lgetxattr                    (__NR_SYSCALL_BASE + 228)
+#define __NR_fgetxattr                    (__NR_SYSCALL_BASE + 229)
+#define __NR_listxattr                    (__NR_SYSCALL_BASE + 230)
+#define __NR_llistxattr                   (__NR_SYSCALL_BASE + 231)
+#define __NR_flistxattr                   (__NR_SYSCALL_BASE + 232)
+#define __NR_removexattr                  (__NR_SYSCALL_BASE + 233)
+#define __NR_lremovexattr                 (__NR_SYSCALL_BASE + 234)
+#define __NR_fremovexattr                 (__NR_SYSCALL_BASE + 235)
+#define __NR_tkill                        (__NR_SYSCALL_BASE + 236)
+#define __NR_futex                        (__NR_SYSCALL_BASE + 238)
+#define __NR_sched_setaffinity            (__NR_SYSCALL_BASE + 239)
+#define __NR_sched_getaffinity            (__NR_SYSCALL_BASE + 240)
+#define __NR_exit_group                   (__NR_SYSCALL_BASE + 246)
+#define __NR_epoll_create                 (__NR_SYSCALL_BASE + 248)
+#define __NR_epoll_ctl                    (__NR_SYSCALL_BASE + 249)
+#define __NR_epoll_wait                   (__NR_SYSCALL_BASE + 250)
+#define __NR_statfs64                     (__NR_SYSCALL_BASE + 255)
+#define __NR_fstatfs64                    (__NR_SYSCALL_BASE + 256)
+#define __NR_timer_create                 (__NR_SYSCALL_BASE + 257)
+#define __NR_timer_settime                (__NR_SYSCALL_BASE + 258)
+#define __NR_timer_gettime                (__NR_SYSCALL_BASE + 259)
+#define __NR_timer_getoverrun             (__NR_SYSCALL_BASE + 260)
+#define __NR_timer_delete                 (__NR_SYSCALL_BASE + 261)
+#define __NR_clock_settime                (__NR_SYSCALL_BASE + 262)
+#define __NR_clock_gettime                (__NR_SYSCALL_BASE + 263)
+#define __NR_clock_getres                 (__NR_SYSCALL_BASE + 264)
+#define __NR_clock_nanosleep              (__NR_SYSCALL_BASE + 265)
+#define __NR_tgkill                       (__NR_SYSCALL_BASE + 266)
+#define __NR_utimes                       (__NR_SYSCALL_BASE + 267)
+#define __NR_waitid                       (__NR_SYSCALL_BASE + 278)
+#define __NR_set_thread_area              (__NR_SYSCALL_BASE + 283)
+#define __NR_inotify_init                 (__NR_SYSCALL_BASE + 284)
+#define __NR_inotify_add_watch            (__NR_SYSCALL_BASE + 285)
+#define __NR_inotify_rm_watch             (__NR_SYSCALL_BASE + 286)
+#define __NR_openat                       (__NR_SYSCALL_BASE + 288)
+#define __NR_mkdirat                      (__NR_SYSCALL_BASE + 289)
+#define __NR_fchownat                     (__NR_SYSCALL_BASE + 291)
+#define __NR_fstatat64                    (__NR_SYSCALL_BASE + 293)
+#define __NR_unlinkat                     (__NR_SYSCALL_BASE + 294)
+#define __NR_renameat                     (__NR_SYSCALL_BASE + 295)
+#define __NR_fchmodat                     (__NR_SYSCALL_BASE + 299)
+#define __NR_faccessat                    (__NR_SYSCALL_BASE + 300)
+#define __NR_getcpu                       (__NR_SYSCALL_BASE + 312)
+#define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 314)
+#define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 315)
+#define __NR_utimensat                    (__NR_SYSCALL_BASE + 316)
+#define __NR_eventfd2                     (__NR_SYSCALL_BASE + 325)
+#define __NR_pipe2                        (__NR_SYSCALL_BASE + 328)
 #endif
 
 #endif
diff --git a/libc/include/time.h b/libc/include/time.h
index 8867b32..e280e0a 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -103,6 +103,7 @@
 #define CLOCK_THREAD_CPUTIME_ID    3
 #define CLOCK_REALTIME_HR          4
 #define CLOCK_MONOTONIC_HR         5
+#define CLOCK_BOOTTIME             7
 
 extern int  timer_create(int, struct sigevent*, timer_t*);
 extern int  timer_delete(timer_t);
diff --git a/libc/inet/inet_ntop.c b/libc/inet/inet_ntop.c
index 5748da3..c3448f1 100644
--- a/libc/inet/inet_ntop.c
+++ b/libc/inet/inet_ntop.c
@@ -75,8 +75,13 @@
 	char tmp[sizeof "255.255.255.255"];
 	int l;
 
+#if defined(ANDROID_CHANGES)
+	l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
+	if (l <= 0 || (size_t)l >= size || (size_t)l >= sizeof(tmp)) {
+#else
 	l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
 	if (l <= 0 || (size_t)l >= size) {
+#endif
 		errno = ENOSPC;
 		return (NULL);
 	}
diff --git a/libc/kernel/arch-arm/asm/ucontext.h b/libc/kernel/arch-arm/asm/ucontext.h
new file mode 100644
index 0000000..b9a879d
--- /dev/null
+++ b/libc/kernel/arch-arm/asm/ucontext.h
@@ -0,0 +1,34 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _ASMARM_UCONTEXT_H
+#define _ASMARM_UCONTEXT_H
+#include <asm/fpstate.h>
+struct ucontext {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ sigset_t uc_sigmask;
+ int _unused[32 - (sizeof (sigset_t) / sizeof (int))];
+ unsigned long uc_regspace[128] __attribute__((__aligned__(8)));
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
diff --git a/libc/kernel/arch-mips/asm/signal.h b/libc/kernel/arch-mips/asm/signal.h
index b51ad71..5f5ac77 100644
--- a/libc/kernel/arch-mips/asm/signal.h
+++ b/libc/kernel/arch-mips/asm/signal.h
@@ -92,32 +92,33 @@
 #define MINSIGSTKSZ 2048
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define SIGSTKSZ 8192
+struct siginfo;
 #define SIG_BLOCK 1  
 #define SIG_UNBLOCK 2  
-#define SIG_SETMASK 3  
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SIG_SETMASK 3  
 #include <asm-generic/signal.h>
 struct sigaction {
  unsigned int sa_flags;
- union {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ union {
  __sighandler_t sa_handler;
  void (*sa_sigaction) (int, struct siginfo *, void *);
  } __sigaction_handler;
-#define sa_handler __sigaction_handler.sa_handler
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define sa_handler __sigaction_handler.sa_handler
 #define sa_sigaction __sigaction_handler.sa_sigaction
  sigset_t sa_mask;
 };
-struct k_sigaction {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct k_sigaction {
  struct sigaction sa;
 };
 typedef struct sigaltstack {
- void *ss_sp;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ void *ss_sp;
  size_t ss_size;
  int ss_flags;
 } stack_t;
-#endif
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
diff --git a/libc/kernel/arch-mips/asm/ucontext.h b/libc/kernel/arch-mips/asm/ucontext.h
new file mode 100644
index 0000000..aa4d67d
--- /dev/null
+++ b/libc/kernel/arch-mips/asm/ucontext.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/ucontext.h>
diff --git a/libc/kernel/arch-x86/asm/ucontext.h b/libc/kernel/arch-x86/asm/ucontext.h
new file mode 100644
index 0000000..e2326e5
--- /dev/null
+++ b/libc/kernel/arch-x86/asm/ucontext.h
@@ -0,0 +1,24 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _ASM_X86_UCONTEXT_H
+#define _ASM_X86_UCONTEXT_H
+#define UC_FP_XSTATE 0x1  
+#include <asm-generic/ucontext.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
diff --git a/libc/kernel/common/asm-generic/ucontext.h b/libc/kernel/common/asm-generic/ucontext.h
new file mode 100644
index 0000000..f26d1cc
--- /dev/null
+++ b/libc/kernel/common/asm-generic/ucontext.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __ASM_GENERIC_UCONTEXT_H
+#define __ASM_GENERIC_UCONTEXT_H
+struct ucontext {
+ unsigned long uc_flags;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
+#endif
diff --git a/libc/kernel/common/linux/fb.h b/libc/kernel/common/linux/fb.h
old mode 100644
new mode 100755
index 52648bc..48eec81
--- a/libc/kernel/common/linux/fb.h
+++ b/libc/kernel/common/linux/fb.h
@@ -242,159 +242,165 @@
 #define FB_VMODE_SMOOTH_XPAN 512  
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define FB_VMODE_CONUPDATE 512  
+#define FB_FLAG_RATIO_4_3 64
+#define FB_FLAG_RATIO_16_9 128
+#define FB_FLAG_PIXEL_REPEAT 256
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FB_FLAG_PREFERRED 512
+#define FB_FLAG_HW_CAPABLE 1024
 #define FB_ROTATE_UR 0
 #define FB_ROTATE_CW 1
-#define FB_ROTATE_UD 2
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FB_ROTATE_UD 2
 #define FB_ROTATE_CCW 3
 #define PICOS2KHZ(a) (1000000000UL/(a))
 #define KHZ2PICOS(a) (1000000000UL/(a))
-struct fb_var_screeninfo {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct fb_var_screeninfo {
  __u32 xres;
  __u32 yres;
  __u32 xres_virtual;
- __u32 yres_virtual;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 yres_virtual;
  __u32 xoffset;
  __u32 yoffset;
  __u32 bits_per_pixel;
- __u32 grayscale;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 grayscale;
  struct fb_bitfield red;
  struct fb_bitfield green;
  struct fb_bitfield blue;
- struct fb_bitfield transp;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct fb_bitfield transp;
  __u32 nonstd;
  __u32 activate;
  __u32 height;
- __u32 width;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 width;
  __u32 accel_flags;
  __u32 pixclock;
  __u32 left_margin;
- __u32 right_margin;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 right_margin;
  __u32 upper_margin;
  __u32 lower_margin;
  __u32 hsync_len;
- __u32 vsync_len;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 vsync_len;
  __u32 sync;
  __u32 vmode;
  __u32 rotate;
- __u32 colorspace;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 colorspace;
  __u32 reserved[4];
 };
 struct fb_cmap {
- __u32 start;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 start;
  __u32 len;
  __u16 *red;
  __u16 *green;
- __u16 *blue;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u16 *blue;
  __u16 *transp;
 };
 struct fb_con2fbmap {
- __u32 console;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 console;
  __u32 framebuffer;
 };
 #define VESA_NO_BLANKING 0
-#define VESA_VSYNC_SUSPEND 1
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define VESA_VSYNC_SUSPEND 1
 #define VESA_HSYNC_SUSPEND 2
 #define VESA_POWERDOWN 3
 enum {
- FB_BLANK_UNBLANK = VESA_NO_BLANKING,
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ FB_BLANK_UNBLANK = VESA_NO_BLANKING,
  FB_BLANK_NORMAL = VESA_NO_BLANKING + 1,
  FB_BLANK_VSYNC_SUSPEND = VESA_VSYNC_SUSPEND + 1,
  FB_BLANK_HSYNC_SUSPEND = VESA_HSYNC_SUSPEND + 1,
- FB_BLANK_POWERDOWN = VESA_POWERDOWN + 1
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ FB_BLANK_POWERDOWN = VESA_POWERDOWN + 1
 };
 #define FB_VBLANK_VBLANKING 0x001  
 #define FB_VBLANK_HBLANKING 0x002  
-#define FB_VBLANK_HAVE_VBLANK 0x004  
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FB_VBLANK_HAVE_VBLANK 0x004  
 #define FB_VBLANK_HAVE_HBLANK 0x008  
 #define FB_VBLANK_HAVE_COUNT 0x010  
 #define FB_VBLANK_HAVE_VCOUNT 0x020  
-#define FB_VBLANK_HAVE_HCOUNT 0x040  
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FB_VBLANK_HAVE_HCOUNT 0x040  
 #define FB_VBLANK_VSYNCING 0x080  
 #define FB_VBLANK_HAVE_VSYNC 0x100  
 struct fb_vblank {
- __u32 flags;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 flags;
  __u32 count;
  __u32 vcount;
  __u32 hcount;
- __u32 reserved[4];
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 reserved[4];
 };
 #define ROP_COPY 0
 #define ROP_XOR 1
-struct fb_copyarea {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct fb_copyarea {
  __u32 dx;
  __u32 dy;
  __u32 width;
- __u32 height;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 height;
  __u32 sx;
  __u32 sy;
 };
-struct fb_fillrect {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct fb_fillrect {
  __u32 dx;
  __u32 dy;
  __u32 width;
- __u32 height;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 height;
  __u32 color;
  __u32 rop;
 };
-struct fb_image {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct fb_image {
  __u32 dx;
  __u32 dy;
  __u32 width;
- __u32 height;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 height;
  __u32 fg_color;
  __u32 bg_color;
  __u8 depth;
- const char *data;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ const char *data;
  struct fb_cmap cmap;
 };
 #define FB_CUR_SETIMAGE 0x01
-#define FB_CUR_SETPOS 0x02
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FB_CUR_SETPOS 0x02
 #define FB_CUR_SETHOT 0x04
 #define FB_CUR_SETCMAP 0x08
 #define FB_CUR_SETSHAPE 0x10
-#define FB_CUR_SETSIZE 0x20
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FB_CUR_SETSIZE 0x20
 #define FB_CUR_SETALL 0xFF
 struct fbcurpos {
  __u16 x, y;
-};
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
 struct fb_cursor {
  __u16 set;
  __u16 enable;
- __u16 rop;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u16 rop;
  const char *mask;
  struct fbcurpos hot;
  struct fb_image image;
-};
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
 #endif
 
diff --git a/libc/kernel/common/linux/filter.h b/libc/kernel/common/linux/filter.h
index 613ee67..e5b2e95 100644
--- a/libc/kernel/common/linux/filter.h
+++ b/libc/kernel/common/linux/filter.h
@@ -23,94 +23,102 @@
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_MAJOR_VERSION 1
 #define BPF_MINOR_VERSION 1
-struct sock_filter
-{
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct sock_filter {
  __u16 code;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __u8 jt;
  __u8 jf;
  __u32 k;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
-struct sock_fprog
-{
- unsigned short len;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct sock_fprog {
+ unsigned short len;
  struct sock_filter __user *filter;
 };
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_CLASS(code) ((code) & 0x07)
 #define BPF_LD 0x00
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_LDX 0x01
 #define BPF_ST 0x02
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_STX 0x03
 #define BPF_ALU 0x04
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_JMP 0x05
 #define BPF_RET 0x06
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_MISC 0x07
 #define BPF_SIZE(code) ((code) & 0x18)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_W 0x00
 #define BPF_H 0x08
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_B 0x10
 #define BPF_MODE(code) ((code) & 0xe0)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_IMM 0x00
 #define BPF_ABS 0x20
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_IND 0x40
 #define BPF_MEM 0x60
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_LEN 0x80
 #define BPF_MSH 0xa0
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_OP(code) ((code) & 0xf0)
 #define BPF_ADD 0x00
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_SUB 0x10
 #define BPF_MUL 0x20
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_DIV 0x30
 #define BPF_OR 0x40
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_AND 0x50
 #define BPF_LSH 0x60
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_RSH 0x70
 #define BPF_NEG 0x80
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_JA 0x00
 #define BPF_JEQ 0x10
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_JGT 0x20
 #define BPF_JGE 0x30
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_JSET 0x40
 #define BPF_SRC(code) ((code) & 0x08)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_K 0x00
 #define BPF_X 0x08
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_RVAL(code) ((code) & 0x18)
 #define BPF_A 0x10
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_MISCOP(code) ((code) & 0xf8)
 #define BPF_TAX 0x00
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_TXA 0x80
 #ifndef BPF_MAXINSNS
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_MAXINSNS 4096
 #endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #ifndef BPF_STMT
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #endif
 #ifndef BPF_JUMP
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
 #endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define BPF_MEMWORDS 16
 #define SKF_AD_OFF (-0x1000)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define SKF_AD_PROTOCOL 0
 #define SKF_AD_PKTTYPE 4
-#define SKF_AD_IFINDEX 8
-#define SKF_AD_MAX 12
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SKF_AD_IFINDEX 8
+#define SKF_AD_NLATTR 12
+#define SKF_AD_NLATTR_NEST 16
+#define SKF_AD_MARK 20
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SKF_AD_QUEUE 24
+#define SKF_AD_HATYPE 28
+#define SKF_AD_RXHASH 32
+#define SKF_AD_CPU 36
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SKF_AD_ALU_XOR_X 40
+#define SKF_AD_MAX 44
 #define SKF_NET_OFF (-0x100000)
 #define SKF_LL_OFF (-0x200000)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #endif
diff --git a/libc/kernel/common/linux/ion.h b/libc/kernel/common/linux/ion.h
index b8715a3..0f872ec 100644
--- a/libc/kernel/common/linux/ion.h
+++ b/libc/kernel/common/linux/ion.h
@@ -33,34 +33,38 @@
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
 #define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
+#define ION_FLAG_CACHED 1  
 struct ion_allocation_data {
- size_t len;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ size_t len;
  size_t align;
+ unsigned int heap_mask;
  unsigned int flags;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  struct ion_handle *handle;
 };
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 struct ion_fd_data {
  struct ion_handle *handle;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  int fd;
 };
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 struct ion_handle_data {
  struct ion_handle *handle;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
 struct ion_custom_data {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  unsigned int cmd;
  unsigned long arg;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
 #define ION_IOC_MAGIC 'I'
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0,   struct ion_allocation_data)
 #define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
 #define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, int)
 #define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #endif
+
diff --git a/libc/kernel/common/linux/prctl.h b/libc/kernel/common/linux/prctl.h
index 8906639..5e79143 100644
--- a/libc/kernel/common/linux/prctl.h
+++ b/libc/kernel/common/linux/prctl.h
@@ -64,5 +64,57 @@
 #define PR_ENDIAN_BIG 0
 #define PR_ENDIAN_LITTLE 1  
 #define PR_ENDIAN_PPC_LITTLE 2  
-#endif
+#define PR_GET_SECCOMP 21
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_SET_SECCOMP 22
+#define PR_CAPBSET_READ 23
+#define PR_CAPBSET_DROP 24
+#define PR_GET_TSC 25
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_SET_TSC 26
+#define PR_TSC_ENABLE 1  
+#define PR_TSC_SIGSEGV 2  
+#define PR_GET_SECUREBITS 27
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_SET_SECUREBITS 28
+#define PR_SET_TIMERSLACK 29
+#define PR_GET_TIMERSLACK 30
+#define PR_TASK_PERF_EVENTS_DISABLE 31
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_TASK_PERF_EVENTS_ENABLE 32
+#define PR_MCE_KILL 33
+#define PR_MCE_KILL_CLEAR 0
+#define PR_MCE_KILL_SET 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_MCE_KILL_LATE 0
+#define PR_MCE_KILL_EARLY 1
+#define PR_MCE_KILL_DEFAULT 2
+#define PR_MCE_KILL_GET 34
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_SET_MM 35
+#define PR_SET_MM_START_CODE 1
+#define PR_SET_MM_END_CODE 2
+#define PR_SET_MM_START_DATA 3
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_SET_MM_END_DATA 4
+#define PR_SET_MM_START_STACK 5
+#define PR_SET_MM_START_BRK 6
+#define PR_SET_MM_BRK 7
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_SET_MM_ARG_START 8
+#define PR_SET_MM_ARG_END 9
+#define PR_SET_MM_ENV_START 10
+#define PR_SET_MM_ENV_END 11
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_SET_MM_AUXV 12
+#define PR_SET_MM_EXE_FILE 13
+#define PR_SET_PTRACER 0x59616d61
+#define PR_SET_PTRACER_ANY ((unsigned long)-1)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_SET_CHILD_SUBREAPER 36
+#define PR_GET_CHILD_SUBREAPER 37
+#define PR_SET_NO_NEW_PRIVS 38
+#define PR_GET_NO_NEW_PRIVS 39
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PR_GET_TID_ADDRESS 40
+#endif
diff --git a/libc/kernel/common/linux/seccomp.h b/libc/kernel/common/linux/seccomp.h
new file mode 100644
index 0000000..82a6985
--- /dev/null
+++ b/libc/kernel/common/linux/seccomp.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_SECCOMP_H
+#define _LINUX_SECCOMP_H
+#include <linux/compiler.h>
+#include <linux/types.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SECCOMP_MODE_DISABLED 0  
+#define SECCOMP_MODE_STRICT 1  
+#define SECCOMP_MODE_FILTER 2  
+#define SECCOMP_RET_KILL 0x00000000U  
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SECCOMP_RET_TRAP 0x00030000U  
+#define SECCOMP_RET_ERRNO 0x00050000U  
+#define SECCOMP_RET_TRACE 0x7ff00000U  
+#define SECCOMP_RET_ALLOW 0x7fff0000U  
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SECCOMP_RET_ACTION 0x7fff0000U
+#define SECCOMP_RET_DATA 0x0000ffffU
+struct seccomp_data {
+ int nr;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 arch;
+ __u64 instruction_pointer;
+ __u64 args[6];
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
diff --git a/libc/kernel/common/linux/watchdog.h b/libc/kernel/common/linux/watchdog.h
new file mode 100644
index 0000000..4cbff4b
--- /dev/null
+++ b/libc/kernel/common/linux/watchdog.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_WATCHDOG_H
+#define _LINUX_WATCHDOG_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WATCHDOG_IOCTL_BASE 'W'
+struct watchdog_info {
+ __u32 options;
+ __u32 firmware_version;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u8 identity[32];
+};
+#define WDIOC_GETSUPPORT _IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
+#define WDIOC_GETSTATUS _IOR(WATCHDOG_IOCTL_BASE, 1, int)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WDIOC_GETBOOTSTATUS _IOR(WATCHDOG_IOCTL_BASE, 2, int)
+#define WDIOC_GETTEMP _IOR(WATCHDOG_IOCTL_BASE, 3, int)
+#define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int)
+#define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
+#define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int)
+#define WDIOC_SETPRETIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 8, int)
+#define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int)
+#define WDIOF_UNKNOWN -1  
+#define WDIOS_UNKNOWN -1  
+#define WDIOF_OVERHEAT 0x0001  
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WDIOF_FANFAULT 0x0002  
+#define WDIOF_EXTERN1 0x0004  
+#define WDIOF_EXTERN2 0x0008  
+#define WDIOF_POWERUNDER 0x0010  
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WDIOF_CARDRESET 0x0020  
+#define WDIOF_POWEROVER 0x0040  
+#define WDIOF_SETTIMEOUT 0x0080  
+#define WDIOF_MAGICCLOSE 0x0100  
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WDIOF_PRETIMEOUT 0x0200  
+#define WDIOF_KEEPALIVEPING 0x8000  
+#define WDIOS_DISABLECARD 0x0001  
+#define WDIOS_ENABLECARD 0x0002  
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WDIOS_TEMPPANIC 0x0004  
+#endif
diff --git a/libc/netbsd/net/getnameinfo.c b/libc/netbsd/net/getnameinfo.c
index 8a1e95e..d8ac037 100644
--- a/libc/netbsd/net/getnameinfo.c
+++ b/libc/netbsd/net/getnameinfo.c
@@ -53,7 +53,9 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <net/if.h>
+#if defined(ANDROID_CHANGES) && defined(AF_LINK)
 #include <net/if_dl.h>
+#endif
 #include <net/if_ieee1394.h>
 #include <net/if_types.h>
 #include <netinet/in.h>
@@ -104,8 +106,10 @@
 static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t,
 				 int));
 #endif
+#if defined(ANDROID_CHANGES) && defined(AF_LINK)
 static int getnameinfo_link __P((const struct sockaddr *, socklen_t, char *,
     socklen_t, char *, socklen_t, int));
+#endif
 static int hexname __P((const u_int8_t *, size_t, char *, socklen_t));
 
 // This should be synchronized to ResponseCode.h
@@ -123,7 +127,7 @@
 	case AF_INET6:
 		return getnameinfo_inet(sa, salen, host, hostlen,
 		    serv, servlen, flags);
-#if 0
+#if defined(ANDROID_CHANGES) && defined(AF_LINK)
 	case AF_LINK:
 		return getnameinfo_link(sa, salen, host, hostlen,
 		    serv, servlen, flags);
@@ -408,7 +412,7 @@
 #endif
 
 		if (hp) {
-#if 0
+#if defined(ANDROID_CHANGES) && defined(AF_LINK)
 			/*
 			 * commented out, since "for local host" is not
 			 * implemented here - see RFC2553 p30
@@ -546,6 +550,7 @@
 #endif /* INET6 */
 
 
+#if defined(ANDROID_CHANGES) && defined(AF_LINK)
 /*
  * getnameinfo_link():
  * Format a link-layer address into a printable format, paying attention to
@@ -623,6 +628,7 @@
 		    (size_t)sdl->sdl_alen, host, hostlen);
 	}
 }
+#endif
 
 static int
 hexname(cp, len, host, hostlen)
diff --git a/libc/netbsd/resolv/res_cache.c b/libc/netbsd/resolv/res_cache.c
index 9ae627c..838e084 100644
--- a/libc/netbsd/resolv/res_cache.c
+++ b/libc/netbsd/resolv/res_cache.c
@@ -1170,6 +1170,15 @@
  * inlined in the Entry structure.
  */
 
+/* Maximum time for a thread to wait for an pending request */
+#define PENDING_REQUEST_TIMEOUT 20;
+
+typedef struct pending_req_info {
+    unsigned int                hash;
+    pthread_cond_t              cond;
+    struct pending_req_info*    next;
+} PendingReqInfo;
+
 typedef struct resolv_cache {
     int              max_entries;
     int              num_entries;
@@ -1178,6 +1187,7 @@
     unsigned         generation;
     int              last_id;
     Entry*           entries;
+    PendingReqInfo   pending_requests;
 } Cache;
 
 typedef struct resolv_cache_info {
@@ -1192,6 +1202,107 @@
 #define  HTABLE_VALID(x)  ((x) != NULL && (x) != HTABLE_DELETED)
 
 static void
+_cache_flush_pending_requests_locked( struct resolv_cache* cache )
+{
+    struct pending_req_info *ri, *tmp;
+    if (cache) {
+        ri = cache->pending_requests.next;
+
+        while (ri) {
+            tmp = ri;
+            ri = ri->next;
+            pthread_cond_broadcast(&tmp->cond);
+
+            pthread_cond_destroy(&tmp->cond);
+            free(tmp);
+        }
+
+        cache->pending_requests.next = NULL;
+    }
+}
+
+/* return 0 if no pending request is found matching the key
+ * if a matching request is found the calling thread will wait
+ * and return 1 when released */
+static int
+_cache_check_pending_request_locked( struct resolv_cache* cache, Entry* key )
+{
+    struct pending_req_info *ri, *prev;
+    int exist = 0;
+
+    if (cache && key) {
+        ri = cache->pending_requests.next;
+        prev = &cache->pending_requests;
+        while (ri) {
+            if (ri->hash == key->hash) {
+                exist = 1;
+                break;
+            }
+            prev = ri;
+            ri = ri->next;
+        }
+
+        if (!exist) {
+            ri = calloc(1, sizeof(struct pending_req_info));
+            if (ri) {
+                ri->hash = key->hash;
+                pthread_cond_init(&ri->cond, NULL);
+                prev->next = ri;
+            }
+        } else {
+            struct timespec ts = {0,0};
+            ts.tv_sec = _time_now() + PENDING_REQUEST_TIMEOUT;
+            int rv = pthread_cond_timedwait(&ri->cond, &cache->lock, &ts);
+        }
+    }
+
+    return exist;
+}
+
+/* notify any waiting thread that waiting on a request
+ * matching the key has been added to the cache */
+static void
+_cache_notify_waiting_tid_locked( struct resolv_cache* cache, Entry* key )
+{
+    struct pending_req_info *ri, *prev;
+
+    if (cache && key) {
+        ri = cache->pending_requests.next;
+        prev = &cache->pending_requests;
+        while (ri) {
+            if (ri->hash == key->hash) {
+                pthread_cond_broadcast(&ri->cond);
+                break;
+            }
+            prev = ri;
+            ri = ri->next;
+        }
+
+        // remove item from list and destroy
+        if (ri) {
+            prev->next = ri->next;
+            pthread_cond_destroy(&ri->cond);
+            free(ri);
+        }
+    }
+}
+
+/* notify the cache that the query failed */
+void
+_resolv_cache_query_failed( struct resolv_cache* cache,
+                   const void* query,
+                   int         querylen)
+{
+    Entry    key[1];
+
+    if (cache && entry_init_key(key, query, querylen)) {
+        pthread_mutex_lock(&cache->lock);
+        _cache_notify_waiting_tid_locked(cache, key);
+        pthread_mutex_unlock(&cache->lock);
+    }
+}
+
+static void
 _cache_flush_locked( Cache*  cache )
 {
     int     nn;
@@ -1208,6 +1319,9 @@
         }
     }
 
+    // flush pending request
+    _cache_flush_pending_requests_locked(cache);
+
     cache->mru_list.mru_next = cache->mru_list.mru_prev = &cache->mru_list;
     cache->num_entries       = 0;
     cache->last_id           = 0;
@@ -1433,6 +1547,27 @@
     _cache_remove_p(cache, lookup);
 }
 
+/* Remove all expired entries from the hash table.
+ */
+static void _cache_remove_expired(Cache* cache) {
+    Entry* e;
+    time_t now = _time_now();
+
+    for (e = cache->mru_list.mru_next; e != &cache->mru_list;) {
+        // Entry is old, remove
+        if (now >= e->expires) {
+            Entry** lookup = _cache_lookup_p(cache, e);
+            if (*lookup == NULL) { /* should not happen */
+                XLOG("%s: ENTRY NOT IN HTABLE ?", __FUNCTION__);
+                return;
+            }
+            e = e->mru_next;
+            _cache_remove_p(cache, lookup);
+        } else {
+            e = e->mru_next;
+        }
+    }
+}
 
 ResolvCacheStatus
 _resolv_cache_lookup( struct resolv_cache*  cache,
@@ -1470,7 +1605,17 @@
 
     if (e == NULL) {
         XLOG( "NOT IN CACHE");
-        goto Exit;
+        // calling thread will wait if an outstanding request is found
+        // that matching this query
+        if (!_cache_check_pending_request_locked(cache, key)) {
+            goto Exit;
+        } else {
+            lookup = _cache_lookup_p(cache, key);
+            e = *lookup;
+            if (e == NULL) {
+                goto Exit;
+            }
+        }
     }
 
     now = _time_now();
@@ -1547,7 +1692,10 @@
     }
 
     if (cache->num_entries >= cache->max_entries) {
-        _cache_remove_oldest(cache);
+        _cache_remove_expired(cache);
+        if (cache->num_entries >= cache->max_entries) {
+            _cache_remove_oldest(cache);
+        }
         /* need to lookup again */
         lookup = _cache_lookup_p(cache, key);
         e      = *lookup;
@@ -1570,6 +1718,7 @@
     _cache_dump_mru(cache);
 #endif
 Exit:
+    _cache_notify_waiting_tid_locked(cache, key);
     pthread_mutex_unlock( &cache->lock );
 }
 
diff --git a/libc/netbsd/resolv/res_send.c b/libc/netbsd/resolv/res_send.c
index dbad6dd..72a7ada 100644
--- a/libc/netbsd/resolv/res_send.c
+++ b/libc/netbsd/resolv/res_send.c
@@ -646,6 +646,9 @@
 		errno = terrno;
 	return (-1);
  fail:
+#if USE_RESOLV_CACHE
+	_resolv_cache_query_failed(cache, buf, buflen);
+#endif
 	res_nclose(statp);
 	return (-1);
 }
@@ -1144,6 +1147,9 @@
 		 * XXX - potential security hazard could
 		 *	 be detected here.
 		 */
+#ifdef ANDROID_CHANGES
+		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_OLD_RESPONSE);
+#endif
 		DprintQ((statp->options & RES_DEBUG) ||
 			(statp->pfcode & RES_PRF_REPLY),
 			(stdout, ";; old answer:\n"),
@@ -1157,6 +1163,9 @@
 		 * XXX - potential security hazard could
 		 *	 be detected here.
 		 */
+#ifdef ANDROID_CHANGES
+		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_SERVER);
+#endif
 		DprintQ((statp->options & RES_DEBUG) ||
 			(statp->pfcode & RES_PRF_REPLY),
 			(stdout, ";; not our server:\n"),
@@ -1187,6 +1196,9 @@
 		 * XXX - potential security hazard could
 		 *	 be detected here.
 		 */
+#ifdef ANDROID_CHANGES
+		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_QUERY);
+#endif
 		DprintQ((statp->options & RES_DEBUG) ||
 			(statp->pfcode & RES_PRF_REPLY),
 			(stdout, ";; wrong query name:\n"),
diff --git a/libdl/arch-sh/soend.S b/libc/private/__dso_handle.h
similarity index 86%
copy from libdl/arch-sh/soend.S
copy to libc/private/__dso_handle.h
index 7fa98a4..e67ce7c 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/private/__dso_handle.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,9 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
 
+#ifndef CRT_LEGACY_WORKAROUND
+__attribute__ ((visibility ("hidden")))
+#endif
+__attribute__ ((section (".bss")))
+void *__dso_handle = (void *) 0;
diff --git a/libdl/arch-sh/soend.S b/libc/private/__dso_handle_so.c
similarity index 89%
rename from libdl/arch-sh/soend.S
rename to libc/private/__dso_handle_so.c
index 7fa98a4..198e64b 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/private/__dso_handle_so.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,7 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
 
+__attribute__ ((visibility ("hidden")))
+__attribute__ ((section (".data")))
+void *__dso_handle;
diff --git a/libc/private/bionic_atomic_gcc_builtin.h b/libc/private/bionic_atomic_gcc_builtin.h
index e7c5761..2919f7f 100644
--- a/libc/private/bionic_atomic_gcc_builtin.h
+++ b/libc/private/bionic_atomic_gcc_builtin.h
@@ -31,18 +31,17 @@
 __bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr)
 {
     /* We must return 0 on success */
-    return __sync_bool_compare_and_swap(ptr, old_value, new_value) == 0;
+    return __sync_val_compare_and_swap(ptr, old_value, new_value) != old_value;
 }
 
 __ATOMIC_INLINE__ int32_t
 __bionic_swap(int32_t new_value, volatile int32_t* ptr)
 {
-    int32_t prev;
+    int32_t old_value;
     do {
-        prev = *ptr;
-        status = __sync_val_compare_and_swap(ptr, prev, new_value);
-    } while (status == 0);
-    return prev;
+        old_value = *ptr;
+    } while (__sync_val_compare_and_swap(ptr, old_value, new_value) != old_value);
+    return old_value;
 }
 
 __ATOMIC_INLINE__ int32_t
diff --git a/libc/private/bionic_atomic_inline.h b/libc/private/bionic_atomic_inline.h
index 821ad39..6819af6 100644
--- a/libc/private/bionic_atomic_inline.h
+++ b/libc/private/bionic_atomic_inline.h
@@ -50,11 +50,13 @@
 #define  __ATOMIC_INLINE__  static __inline__ __attribute__((always_inline))
 
 #ifdef __arm__
-#  include <bionic_atomic_arm.h>
+#  include "bionic_atomic_arm.h"
 #elif defined(__i386__)
-#  include <bionic_atomic_x86.h>
+#  include "bionic_atomic_x86.h"
+#elif defined(__mips__)
+#  include "bionic_atomic_mips.h"
 #else
-#  include <bionic_atomic_gcc_builtin.h>
+#  include "bionic_atomic_gcc_builtin.h"
 #endif
 
 #define ANDROID_MEMBAR_FULL  __bionic_memory_barrier
diff --git a/libc/private/bionic_atomic_mips.h b/libc/private/bionic_atomic_mips.h
new file mode 100644
index 0000000..28fe88d
--- /dev/null
+++ b/libc/private/bionic_atomic_mips.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2011 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 BIONIC_ATOMIC_MIPS_H
+#define BIONIC_ATOMIC_MIPS_H
+
+/* Define a full memory barrier, this is only needed if we build the
+ * platform for a multi-core device.
+ */
+#if defined(ANDROID_SMP) && ANDROID_SMP == 1
+__ATOMIC_INLINE__ void
+__bionic_memory_barrier()
+{
+    __asm__ __volatile__ ( "sync" : : : "memory" );
+}
+#else
+__ATOMIC_INLINE__ void
+__bionic_memory_barrier()
+{
+    /* A simple compiler barrier */
+    __asm__ __volatile__ ( "" : : : "memory" );
+}
+#endif
+
+/* Compare-and-swap, without any explicit barriers. Note that this function
+ * returns 0 on success, and 1 on failure. The opposite convention is typically
+ * used on other platforms.
+ */
+__ATOMIC_INLINE__ int
+__bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr)
+{
+    int32_t prev, status;
+    __asm__ __volatile__ ("1: move %[status], %[new_value]  \n"
+                          "   ll %[prev], 0(%[ptr])         \n"
+                          "   bne %[old_value], %[prev], 2f \n"
+                          "   sc   %[status], 0(%[ptr])     \n"
+                          "   beqz %[status], 1b            \n"
+                          "2:                               \n"
+                          : [prev]"=&r"(prev), [status]"=&r"(status), "+m"(*ptr)
+                          : [new_value]"r"(new_value), [old_value]"r"(old_value), [ptr]"r"(ptr)
+                          : "memory");
+    return prev != old_value;
+}
+
+
+/* Swap, without any explicit barriers */
+__ATOMIC_INLINE__ int32_t
+__bionic_swap(int32_t new_value, volatile int32_t *ptr)
+{
+   int32_t prev, status;
+    __asm__ __volatile__ ("1:  move %[status], %[new_value] \n"
+                          "    ll %[prev], 0(%[ptr])        \n"
+                          "    sc %[status], 0(%[ptr])      \n"
+                          "    beqz %[status], 1b           \n"
+                          : [prev]"=&r"(prev), [status]"=&r"(status), "+m"(*ptr)
+                          : [ptr]"r"(ptr), [new_value]"r"(new_value)
+                          : "memory");
+    return prev;
+}
+
+/* Atomic increment, without explicit barriers */
+__ATOMIC_INLINE__ int32_t
+__bionic_atomic_inc(volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    __asm__ __volatile__ ("1:  ll %[prev], 0(%[ptr])        \n"
+                          "    addiu %[status], %[prev], 1  \n"
+                          "    sc   %[status], 0(%[ptr])    \n"
+                          "    beqz %[status], 1b           \n"
+                          : [prev]"=&r" (prev), [status]"=&r"(status), "+m" (*ptr)
+                          : [ptr]"r"(ptr)
+                          : "memory");
+    return prev;
+}
+
+/* Atomic decrement, without explicit barriers */
+__ATOMIC_INLINE__ int32_t
+__bionic_atomic_dec(volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    __asm__ __volatile__ ("1:  ll %[prev], 0(%[ptr])        \n"
+                          "    addiu %[status], %[prev], -1 \n"
+                          "    sc   %[status], 0(%[ptr])    \n"
+                          "    beqz %[status], 1b           \n"
+                          : [prev]"=&r" (prev), [status]"=&r"(status), "+m" (*ptr)
+                          : [ptr]"r"(ptr)
+                          : "memory");
+    return prev;
+}
+#endif /* BIONIC_ATOMIC_MIPS_H */
diff --git a/libc/private/logd.h b/libc/private/logd.h
index 4a9b62e..8970daf 100644
--- a/libc/private/logd.h
+++ b/libc/private/logd.h
@@ -30,6 +30,21 @@
 
 #include <stdarg.h>
 
+#define BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW 80100
+#define BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW 80105
+#define BIONIC_EVENT_MEMMOVE_BUFFER_OVERFLOW 80110
+#define BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW 80115
+#define BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW 80120
+#define BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW 80125
+#define BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW 80130
+
+#define BIONIC_EVENT_STRCAT_INTEGER_OVERFLOW 80200
+#define BIONIC_EVENT_STRNCAT_INTEGER_OVERFLOW 80205
+
+#define BIONIC_EVENT_RESOLVER_OLD_RESPONSE 80300
+#define BIONIC_EVENT_RESOLVER_WRONG_SERVER 80305
+#define BIONIC_EVENT_RESOLVER_WRONG_QUERY 80310
+
 enum  {
     ANDROID_LOG_UNKNOWN = 0,
     ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
@@ -48,4 +63,7 @@
 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...);
 int __libc_android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap);
 
+void __libc_android_log_event_int(int32_t tag, int value);
+void __libc_android_log_event_uid(int32_t tag);
+
 #endif /* _ANDROID_BIONIC_LOGD_H */
diff --git a/libc/private/resolv_cache.h b/libc/private/resolv_cache.h
index 2a54453..1dcc53f 100644
--- a/libc/private/resolv_cache.h
+++ b/libc/private/resolv_cache.h
@@ -95,4 +95,10 @@
                    const void*           answer,
                    int                   answerlen );
 
+/* Notify the cache a request failed */
+extern void
+_resolv_cache_query_failed( struct resolv_cache* cache,
+                   const void* query,
+                   int         querylen);
+
 #endif /* _RESOLV_CACHE_H_ */
diff --git a/libc/stdio/__fgets_chk.c b/libc/stdio/__fgets_chk.c
new file mode 100644
index 0000000..19123b9
--- /dev/null
+++ b/libc/stdio/__fgets_chk.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <private/logd.h>
+
+/*
+ * __fgets_chk. Called in place of fgets() when we know the
+ * size of the buffer we're writing into.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ * for details.
+ *
+ * This fgets check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+char *__fgets_chk(char *dest, int supplied_size,
+                  FILE *stream, size_t dest_len_from_compiler)
+{
+    if (supplied_size < 0) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** fgets buffer size less than 0 ***\n");
+        abort();
+    }
+
+    if (((size_t) supplied_size) > dest_len_from_compiler) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** fgets buffer overflow detected ***\n");
+        abort();
+    }
+
+    return fgets(dest, supplied_size, stream);
+}
diff --git a/libdl/arch-sh/soend.S b/libc/stdio/__snprintf_chk.c
similarity index 62%
copy from libdl/arch-sh/soend.S
copy to libc/stdio/__snprintf_chk.c
index 7fa98a4..dbda3db 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/stdio/__snprintf_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,34 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <stdio.h>
+#include <stdarg.h>
 
+/*
+ * Runtime implementation of __builtin____snprintf_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This snprintf check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+int __snprintf_chk(
+        char *dest,
+        size_t supplied_size,
+        int flags,
+        size_t dest_len_from_compiler,
+        const char *format, ...)
+{
+    va_list va;
+    int retval;
+
+    va_start(va, format);
+    retval = __vsnprintf_chk(dest, supplied_size, flags,
+                             dest_len_from_compiler, format, va);
+    va_end(va);
+
+    return retval;
+}
diff --git a/libdl/arch-sh/soend.S b/libc/stdio/__sprintf_chk.c
similarity index 64%
copy from libdl/arch-sh/soend.S
copy to libc/stdio/__sprintf_chk.c
index 7fa98a4..67acbe1 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/stdio/__sprintf_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,33 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <stdio.h>
+#include <stdarg.h>
 
+/*
+ * Runtime implementation of __builtin____sprintf_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This sprintf check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+int __sprintf_chk(
+        char *dest,
+        int flags,
+        size_t dest_len_from_compiler,
+        const char *format, ...)
+{
+    va_list va;
+    int retval;
+
+    va_start(va, format);
+    retval = __vsprintf_chk(dest, flags,
+                             dest_len_from_compiler, format, va);
+    va_end(va);
+
+    return retval;
+}
diff --git a/libdl/arch-sh/soend.S b/libc/stdio/__vsnprintf_chk.c
similarity index 60%
copy from libdl/arch-sh/soend.S
copy to libc/stdio/__vsnprintf_chk.c
index 7fa98a4..a1a1039 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/stdio/__vsnprintf_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,35 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <private/logd.h>
 
+/*
+ * Runtime implementation of __builtin____vsnprintf_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This vsnprintf check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+int __vsnprintf_chk(
+        char *dest,
+        size_t supplied_size,
+        int flags,
+        size_t dest_len_from_compiler,
+        const char *format,
+        va_list va)
+{
+    if (supplied_size > dest_len_from_compiler) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** vsnprintf buffer overflow detected ***\n");
+        abort();
+    }
+
+    return vsnprintf(dest, supplied_size, format, va);
+}
diff --git a/libdl/arch-sh/soend.S b/libc/stdio/__vsprintf_chk.c
similarity index 60%
copy from libdl/arch-sh/soend.S
copy to libc/stdio/__vsprintf_chk.c
index 7fa98a4..8a809fc 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/stdio/__vsprintf_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,36 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <private/logd.h>
 
+/*
+ * Runtime implementation of __builtin____vsprintf_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This vsprintf check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+int __vsprintf_chk(
+        char *dest,
+        int flags,
+        size_t dest_len_from_compiler,
+        const char *format,
+        va_list va)
+{
+    int ret = vsnprintf(dest, dest_len_from_compiler, format, va);
+
+    if ((size_t) ret >= dest_len_from_compiler) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** vsprintf buffer overflow detected ***\n");
+        abort();
+    }
+
+    return ret;
+}
diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c
index dac8496..427fc7f 100644
--- a/libc/stdio/vfprintf.c
+++ b/libc/stdio/vfprintf.c
@@ -559,7 +559,7 @@
 #endif /* FLOATING_POINT */
 /* the Android security team suggests removing support for %n
  * since it has no real practical value, and could lead to
- * running malicious code (for really bugy programs that
+ * running malicious code (for really buggy programs that
  * send to printf() user-generated formatting strings).
  */
 #if 0
diff --git a/libc/stdlib/assert.c b/libc/stdlib/assert.c
index 816b050..7c0a860 100644
--- a/libc/stdlib/assert.c
+++ b/libc/stdlib/assert.c
@@ -32,23 +32,23 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <private/logd.h>
 
-void
-__assert(const char *file, int line, const char *failedexpr)
-{
-	(void)fprintf(stderr,
-	    "assertion \"%s\" failed: file \"%s\", line %d\n",
-	    failedexpr, file, line);
-	abort();
-	/* NOTREACHED */
+// We log to stderr for the benefit of "adb shell" users, and the log for the benefit
+// of regular app developers who want to see their asserts.
+
+void __assert(const char* file, int line, const char* failed_expression) {
+  const char* fmt = "%s:%d: assertion \"%s\" failed\n";
+  __libc_android_log_print(ANDROID_LOG_FATAL, "libc", fmt, file, line, failed_expression);
+  fprintf(stderr, fmt, file, line, failed_expression);
+  abort();
+  /* NOTREACHED */
 }
 
-void
-__assert2(const char *file, int line, const char *func, const char *failedexpr)
-{
-	(void)fprintf(stderr,
-	    "assertion \"%s\" failed: file \"%s\", line %d, function \"%s\"\n",
-	    failedexpr, file, line, func);
-	abort();
-	/* NOTREACHED */
+void __assert2(const char* file, int line, const char* function, const char* failed_expression) {
+  const char* fmt = "%s:%d: %s: assertion \"%s\" failed\n";
+  __libc_android_log_print(ANDROID_LOG_FATAL, "libc", fmt, file, line, function, failed_expression);
+  fprintf(stderr, fmt, file, line, function, failed_expression);
+  abort();
+  /* NOTREACHED */
 }
diff --git a/libdl/arch-sh/soend.S b/libc/string/__memcpy_chk.c
similarity index 60%
copy from libdl/arch-sh/soend.S
copy to libc/string/__memcpy_chk.c
index 7fa98a4..10334ba 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/string/__memcpy_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,31 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#undef _FORTIFY_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
+/*
+ * Runtime implementation of __memcpy_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This memcpy check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+void *__memcpy_chk(void *dest, const void *src,
+              size_t copy_amount, size_t dest_len)
+{
+    if (__builtin_expect(copy_amount > dest_len, 0)) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** memcpy buffer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW);
+        abort();
+    }
+
+    return memcpy(dest, src, copy_amount);
+}
diff --git a/libdl/arch-sh/soend.S b/libc/string/__memmove_chk.c
similarity index 62%
copy from libdl/arch-sh/soend.S
copy to libc/string/__memmove_chk.c
index 7fa98a4..529eb8f 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/string/__memmove_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,30 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
+/*
+ * Runtime implementation of __builtin____memmove_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This memmove check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+void *__memmove_chk (void *dest, const void *src,
+              size_t len, size_t dest_len)
+{
+    if (len > dest_len) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** memmove buffer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_MEMMOVE_BUFFER_OVERFLOW);
+        abort();
+    }
+
+    return memmove(dest, src, len);
+}
diff --git a/libdl/arch-sh/soend.S b/libc/string/__memset_chk.c
similarity index 63%
copy from libdl/arch-sh/soend.S
copy to libc/string/__memset_chk.c
index 7fa98a4..0904c03 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/string/__memset_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,29 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
+/*
+ * Runtime implementation of __builtin____memset_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This memset check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+void *__memset_chk (void *dest, int c, size_t n, size_t dest_len)
+{
+    if (n > dest_len) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** memset buffer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW);
+        abort();
+    }
+
+    return memset(dest, c, n);
+}
diff --git a/libc/string/__strcat_chk.c b/libc/string/__strcat_chk.c
new file mode 100644
index 0000000..4665d66
--- /dev/null
+++ b/libc/string/__strcat_chk.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
+#include <safe_iop.h>
+
+/*
+ * Runtime implementation of __builtin____strcat_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This strcat check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+char *__strcat_chk (char *dest, const char *src, size_t dest_buf_size)
+{
+    // TODO: optimize so we don't scan src/dest twice.
+    size_t src_len  = strlen(src);
+    size_t dest_len = strlen(dest);
+    size_t sum;
+
+    // sum = src_len + dest_len + 1 (with overflow protection)
+    if (!safe_add3(&sum, src_len, dest_len, 1U)) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strcat integer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_STRCAT_INTEGER_OVERFLOW);
+        abort();
+    }
+
+    if (sum > dest_buf_size) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strcat buffer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW);
+        abort();
+    }
+
+    return strcat(dest, src);
+}
diff --git a/libdl/arch-sh/soend.S b/libc/string/__strcpy_chk.c
similarity index 60%
copy from libdl/arch-sh/soend.S
copy to libc/string/__strcpy_chk.c
index 7fa98a4..79486b4 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/string/__strcpy_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,31 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
+/*
+ * Runtime implementation of __builtin____strcpy_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This strcpy check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+char *__strcpy_chk (char *dest, const char *src, size_t dest_len)
+{
+    // TODO: optimize so we don't scan src twice.
+    size_t src_len = strlen(src) + 1;
+    if (src_len > dest_len) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strcpy buffer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW);
+        abort();
+    }
+
+    return strcpy(dest, src);
+}
diff --git a/libdl/arch-sh/soend.S b/libc/string/__strlcat_chk.c
similarity index 61%
copy from libdl/arch-sh/soend.S
copy to libc/string/__strlcat_chk.c
index 7fa98a4..b895fb8 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/string/__strlcat_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,30 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
+/*
+ * __strlcat_chk. Called in place of strlcat() when we know the
+ * size of the buffer we're writing into.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This strlcat check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+size_t __strlcat_chk(char *dest, const char *src,
+              size_t supplied_size, size_t dest_len_from_compiler)
+{
+    if (supplied_size > dest_len_from_compiler) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strlcat buffer overflow detected ***\n");
+        abort();
+    }
+
+    return strlcat(dest, src, supplied_size);
+}
diff --git a/libdl/arch-sh/soend.S b/libc/string/__strlcpy_chk.c
similarity index 61%
copy from libdl/arch-sh/soend.S
copy to libc/string/__strlcpy_chk.c
index 7fa98a4..752c86c 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/string/__strlcpy_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,30 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
+/*
+ * __strlcpy_chk. Called in place of strlcpy() when we know the
+ * size of the buffer we're writing into.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This strlcpy check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+size_t __strlcpy_chk(char *dest, const char *src,
+              size_t supplied_size, size_t dest_len_from_compiler)
+{
+    if (supplied_size > dest_len_from_compiler) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strlcpy buffer overflow detected ***\n");
+        abort();
+    }
+
+    return strlcpy(dest, src, supplied_size);
+}
diff --git a/libc/string/__strlen_chk.c b/libc/string/__strlen_chk.c
new file mode 100644
index 0000000..43e7e80
--- /dev/null
+++ b/libc/string/__strlen_chk.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
+
+/*
+ * Runtime implementation of __strlen_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This strlen check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ *
+ * This test is designed to detect code such as:
+ *
+ * int main() {
+ *   char buf[10];
+ *   memcpy(buf, "1234567890", sizeof(buf));
+ *   size_t len = strlen(buf); // segfault here with _FORTIFY_SOURCE
+ *   printf("%d\n", len);
+ *   return 0;
+ * }
+ *
+ * or anytime strlen reads beyond an object boundary.
+ */
+size_t __strlen_chk(const char *s, size_t s_len)
+{
+    size_t ret = strlen(s);
+
+    if (__builtin_expect(ret >= s_len, 0)) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strlen read overflow detected ***\n");
+        abort();
+    }
+
+    return ret;
+}
diff --git a/libc/string/__strncat_chk.c b/libc/string/__strncat_chk.c
new file mode 100644
index 0000000..2036c9f
--- /dev/null
+++ b/libc/string/__strncat_chk.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
+#include <safe_iop.h>
+
+/*
+ * Runtime implementation of __builtin____strncat_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This strncat check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+char *__strncat_chk (char *dest, const char *src,
+              size_t len, size_t dest_buf_size)
+{
+    // TODO: optimize so we don't scan src/dest twice.
+    size_t dest_len = strlen(dest);
+    size_t src_len = strlen(src);
+    if (src_len > len) {
+        src_len = len;
+    }
+
+    size_t sum;
+    // sum = src_len + dest_len + 1 (with overflow protection)
+    if (!safe_add3(&sum, src_len, dest_len, 1U)) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strncat integer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_STRNCAT_INTEGER_OVERFLOW);
+        abort();
+    }
+
+    if (sum > dest_buf_size) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strncat buffer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW);
+        abort();
+    }
+
+    return strncat(dest, src, len);
+}
diff --git a/libdl/arch-sh/soend.S b/libc/string/__strncpy_chk.c
similarity index 62%
copy from libdl/arch-sh/soend.S
copy to libc/string/__strncpy_chk.c
index 7fa98a4..3f9e9fb 100644
--- a/libdl/arch-sh/soend.S
+++ b/libc/string/__strncpy_chk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,30 @@
  * SUCH DAMAGE.
  */
 
-    .section .ctors, "aw"
-    .long 0
+#include <string.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
+/*
+ * Runtime implementation of __builtin____strncpy_chk.
+ *
+ * See
+ *   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+ *   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+ * for details.
+ *
+ * This strncpy check is called if _FORTIFY_SOURCE is defined and
+ * greater than 0.
+ */
+char *__strncpy_chk (char *dest, const char *src,
+              size_t len, size_t dest_len)
+{
+    if (len > dest_len) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** strncpy buffer overflow detected ***\n");
+        __libc_android_log_event_uid(BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW);
+        abort();
+    }
+
+    return strncpy(dest, src, len);
+}
diff --git a/libc/string/memmove.c b/libc/string/memmove.c
index 072104b..a9fc1b5 100644
--- a/libc/string/memmove.c
+++ b/libc/string/memmove.c
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+#undef _FORTIFY_SOURCE
 #include <string.h>
 #include <strings.h>
 
@@ -32,10 +33,11 @@
 {
   const char *p = src;
   char *q = dst;
-  /* We can use the optimized memcpy if the destination is below the
-   * source (i.e. q < p), or if it is completely over it (i.e. q >= p+n).
+  /* We can use the optimized memcpy if the source and destination
+   * don't overlap.
    */
-  if (__builtin_expect((q < p) || ((size_t)(q - p) >= n), 1)) {
+  if (__builtin_expect(((q < p) && ((size_t)(p - q) >= n))
+                    || ((p < q) && ((size_t)(q - p) >= n)), 1)) {
     return memcpy(dst, src, n);
   } else {
     bcopy(src, dst, n);
diff --git a/libc/tools/bionic_utils.py b/libc/tools/bionic_utils.py
index 0bc947b..abb7820 100644
--- a/libc/tools/bionic_utils.py
+++ b/libc/tools/bionic_utils.py
@@ -4,13 +4,13 @@
 
 # support Bionic architectures, add new ones as appropriate
 #
-bionic_archs = [ "arm", "x86" ]
+bionic_archs = [ "arm", "x86", "mips" ]
 
 # basic debugging trace support
 # call D_setlevel to set the verbosity level
 # and D(), D2(), D3(), D4() to add traces
 #
-verbose = 1
+verbose = 0
 
 def D(msg):
     global verbose
@@ -178,7 +178,7 @@
         self.syscalls = []
         self.lineno   = 0
 
-    def E(msg):
+    def E(self, msg):
         print "%d: %s" % (self.lineno, msg)
 
     def parse_line(self, line):
@@ -238,36 +238,55 @@
 
         number = line[pos_rparen+1:].strip()
         if number == "stub":
-            syscall_id  = -1
-            syscall_id2 = -1
+            syscall_common = -1
+            syscall_arm  = -1
+            syscall_x86 = -1
+            syscall_mips = -1
         else:
             try:
                 if number[0] == '#':
                     number = number[1:].strip()
                 numbers = string.split(number,',')
-                syscall_id  = int(numbers[0])
-                syscall_id2 = syscall_id
-                if len(numbers) > 1:
-                    syscall_id2 = int(numbers[1])
+                if len(numbers) == 1:
+                    syscall_common = int(numbers[0])
+                    syscall_arm = -1
+                    syscall_x86 = -1
+                    syscall_mips = -1
+                else:
+                    if len(numbers) == 3:
+                        syscall_common = -1
+                        syscall_arm  = int(numbers[0])
+                        syscall_x86 = int(numbers[1])
+                        syscall_mips = int(numbers[2])
+                    else:
+                        E("invalid syscall number format in '%s'" % line)
+                        return
             except:
                 E("invalid syscall number in '%s'" % line)
                 return
 
-		global verbose
+        global verbose
         if verbose >= 2:
-            if call_id < 0:
-                print "%s: %d,%d" % (syscall_name, syscall_id, syscall_id2)
+            if call_id == -1:
+                if syscall_common == -1:
+                    print "%s: %d,%d,%d" % (syscall_name, syscall_arm, syscall_x86, syscall_mips)
+                else:
+                    print "%s: %d" % (syscall_name, syscall_common)
             else:
-                print "%s(%d): %d,%d" % (syscall_name, call_id, syscall_id, syscall_id2)
+                if syscall_common == -1:
+                    print "%s(%d): %d,%d,%d" % (syscall_name, call_id, syscall_arm, syscall_x86, syscall_mips)
+                else:
+                    print "%s(%d): %d" % (syscall_name, call_id, syscall_common)
 
-        t = { "id"     : syscall_id,
-              "id2"    : syscall_id2,
+        t = { "armid"  : syscall_arm,
+              "x86id"  : syscall_x86,
+              "mipsid" : syscall_mips,
+              "common" : syscall_common,
               "cid"    : call_id,
               "name"   : syscall_name,
               "func"   : syscall_func,
               "params" : syscall_params,
               "decl"   : "%-15s  %s (%s);" % (return_type, syscall_func, params) }
-
         self.syscalls.append(t)
 
     def parse_file(self, file_path):
diff --git a/libc/tools/checksyscalls.py b/libc/tools/checksyscalls.py
index 2c563d7..286e727 100755
--- a/libc/tools/checksyscalls.py
+++ b/libc/tools/checksyscalls.py
@@ -70,10 +70,17 @@
 re_nr_clock_line = re.compile( r"#define __NR_(\w*)\s*\(__NR_timer_create\+(\w*)\)" )
 re_arm_nr_line   = re.compile( r"#define __ARM_NR_(\w*)\s*\(__ARM_NR_BASE\+\s*(\w*)\)" )
 re_x86_line      = re.compile( r"#define __NR_(\w*)\s*([0-9]*)" )
+re_mips_line     = re.compile( r"#define __NR_(\w*)\s*\(__NR_Linux\s*\+\s*([0-9]*)\)" )
 
 # now read the Linux arm header
 def process_nr_line(line,dict):
 
+    m = re_mips_line.match(line)
+    if m:
+        if dict["Linux"]==4000:
+            dict[m.group(1)] = int(m.group(2))
+        return
+
     m = re_nr_line.match(line)
     if m:
         dict[m.group(1)] = int(m.group(2))
@@ -118,6 +125,7 @@
 
 arm_dict = {}
 x86_dict = {}
+mips_dict = {}
 
 # remove trailing slash from the linux_root, if any
 if linux_root[-1] == '/':
@@ -141,8 +149,15 @@
         print "maybe using a different set of kernel headers might help."
         sys.exit(1)
 
+mips_unistd = find_arch_header(linux_root, "mips", "unistd.h")
+if not mips_unistd:
+    print "WEIRD: Could not locate the Mips unistd.h kernel header file,"
+    print "maybe using a different set of kernel headers might help."
+    sys.exit(1)
+
 process_header( arm_unistd, arm_dict )
 process_header( x86_unistd, x86_dict )
+process_header( mips_unistd, mips_dict )
 
 # now perform the comparison
 errors = 0
@@ -154,18 +169,19 @@
         sc_id   = sc[idname]
         if sc_id >= 0:
             if not arch_dict.has_key(sc_name):
-                print "%s syscall %s not defined, should be %d !!" % (archname, sc_name, sc_id)
+                print "error: %s syscall %s not defined, should be %d" % (archname, sc_name, sc_id)
                 errors += 1
             elif not arch_dict.has_key(sc_name):
-                print "%s syscall %s is not implemented!" % (archname, sc_name)
+                print "error: %s syscall %s is not implemented" % (archname, sc_name)
                 errors += 1
             elif arch_dict[sc_name] != sc_id:
-                print "%s syscall %s should be %d instead of %d !!" % (archname, sc_name, arch_dict[sc_name], sc_id)
+                print "error: %s syscall %s should be %d instead of %d" % (archname, sc_name, arch_dict[sc_name], sc_id)
                 errors += 1
     return errors
 
-errors += check_syscalls("arm", "id", arm_dict)
-errors += check_syscalls("x86", "id2", x86_dict)
+errors += check_syscalls("arm", "armid", arm_dict)
+errors += check_syscalls("x86", "x86id", x86_dict)
+errors += check_syscalls("mips", "mipsid", mips_dict)
 
 if errors == 0:
     print "congratulations, everything's fine !!"
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index bfa9fcc..21d2f1d 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -1,11 +1,12 @@
 #!/usr/bin/python
 #
-# this tool is used to generate the syscall assmbler templates
-# to be placed into arch-x86/syscalls, as well as the content
-# of arch-x86/linux/_syscalls.h
+# this tool is used to generate the syscall assembler templates
+# to be placed into arch-{arm,x86,mips}/syscalls, as well as the content
+# of arch-{arm,x86,mips}/linux/_syscalls.h
 #
 
 import sys, os.path, glob, re, commands, filecmp, shutil
+import getpass
 
 from bionic_utils import *
 
@@ -31,9 +32,10 @@
 bionic_temp = "/tmp/bionic_gensyscalls/"
 
 # all architectures, update as you see fit
-all_archs = [ "arm", "x86" ]
+all_archs = [ "arm", "x86", "mips" ]
 
 def make_dir( path ):
+    path = os.path.abspath(path)
     if not os.path.exists(path):
         parent = os.path.dirname(path)
         if parent:
@@ -183,6 +185,32 @@
     .fnend
 """
 
+# mips assembler templates for each syscall stub
+#
+mips_call = """/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl %(fname)s
+    .align 4
+    .ent %(fname)s
+
+%(fname)s:
+    .set noreorder
+    .cpload $t9
+    li $v0, %(idname)s
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end %(fname)s
+"""
+
 def param_uses_64bits(param):
     """Returns True iff a syscall parameter description corresponds
        to a 64-bit type."""
@@ -331,23 +359,10 @@
                 return thumb_call_long % t
         return thumb_call_default % t
 
-
-    def superh_genstub(self, fname, flags, idname):
-        numargs = int(flags)
+    def mips_genstub(self,fname, idname):
         t = { "fname"  : fname,
-              "idname" : idname,
-              "numargs" : numargs }
-        superh_call = superh_header
-        if flags:
-            if numargs == 5:
-                superh_call += superh_5args_header
-            if numargs == 6:
-                superh_call += superh_6args_header
-            if numargs == 7:
-                superh_call += superh_7args_header
-        superh_call += superh_call_default
-        return superh_call % t
-
+              "idname" : idname }
+        return mips_call % t
 
     def process_file(self,input):
         parser = SysCallsTxtParser()
@@ -360,7 +375,7 @@
             syscall_params = t["params"]
             syscall_name   = t["name"]
 
-            if t["id"] >= 0:
+            if t["common"] >= 0 or t["armid"] >= 0:
                 num_regs = count_arm_param_registers(syscall_params)
                 if gen_thumb_stubs:
                     t["asm-thumb"] = self.thumb_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
@@ -370,7 +385,7 @@
                     else:
                         t["asm-arm"]   = self.arm_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
 
-            if t["id2"] >= 0:
+            if t["common"] >= 0 or t["x86id"] >= 0:
                 num_regs = count_generic_param_registers(syscall_params)
                 if t["cid"] >= 0:
                     t["asm-x86"] = self.x86_genstub_cid(syscall_func, num_regs, "__NR_"+syscall_name, t["cid"])
@@ -380,55 +395,65 @@
                 E("cid for dispatch syscalls is only supported for x86 in "
                   "'%s'" % syscall_name)
                 return
+            if t["common"] >= 0 or t["mipsid"] >= 0:
+                t["asm-mips"] = self.mips_genstub(syscall_func,"__NR_"+syscall_name)
 
 
     def gen_NR_syscall(self,fp,name,id):
         fp.write( "#define __NR_%-25s    (__NR_SYSCALL_BASE + %d)\n" % (name,id) )
 
-    # now dump the content of linux/_syscalls.h
+    # now dump the content of linux-syscalls.h
     def gen_linux_syscalls_h(self):
         path = "include/sys/linux-syscalls.h"
         D( "generating "+path )
         fp = create_file( path )
         fp.write( "/* auto-generated by gensyscalls.py, do not touch */\n" )
-        fp.write( "#ifndef _BIONIC_LINUX_SYSCALLS_H_\n\n" )
-        fp.write( "#if !defined __ASM_ARM_UNISTD_H && !defined __ASM_I386_UNISTD_H\n" )
+        fp.write( "#ifndef _BIONIC_LINUX_SYSCALLS_H_\n" )
+        fp.write( "#define _BIONIC_LINUX_SYSCALLS_H_\n\n" )
+        fp.write( "#if !defined __ASM_ARM_UNISTD_H && !defined __ASM_I386_UNISTD_H && !defined __ASM_MIPS_UNISTD_H\n" )
         fp.write( "#if defined __arm__ && !defined __ARM_EABI__ && !defined __thumb__\n" )
-        fp.write( "  #  define __NR_SYSCALL_BASE  0x900000\n" )
-        fp.write( "  #else\n" )
-        fp.write( "  #  define  __NR_SYSCALL_BASE  0\n" )
-        fp.write( "  #endif\n\n" )
+        fp.write( "  #  define __NR_SYSCALL_BASE 0x900000\n" )
+        fp.write( "#elif defined(__mips__)\n" )
+        fp.write( "  #  define __NR_SYSCALL_BASE 4000\n" )
+        fp.write( "#else\n" )
+        fp.write( "  #  define __NR_SYSCALL_BASE 0\n" )
+        fp.write( "#endif\n\n" )
 
         # first, all common syscalls
-        for sc in self.syscalls:
-            sc_id  = sc["id"]
-            sc_id2 = sc["id2"]
+        for sc in sorted(self.syscalls,key=lambda x:x["common"]):
+            sc_id  = sc["common"]
             sc_name = sc["name"]
-            if sc_id == sc_id2 and sc_id >= 0:
+            if sc_id >= 0:
                 self.gen_NR_syscall( fp, sc_name, sc_id )
 
         # now, all arm-specific syscalls
         fp.write( "\n#ifdef __arm__\n" );
         for sc in self.syscalls:
-            sc_id  = sc["id"]
-            sc_id2 = sc["id2"]
+            sc_id  = sc["armid"]
             sc_name = sc["name"]
-            if sc_id != sc_id2 and sc_id >= 0:
+            if sc_id >= 0:
                 self.gen_NR_syscall( fp, sc_name, sc_id )
         fp.write( "#endif\n" );
 
         gen_syscalls = {}
         # finally, all i386-specific syscalls
         fp.write( "\n#ifdef __i386__\n" );
-        for sc in self.syscalls:
-            sc_id  = sc["id"]
-            sc_id2 = sc["id2"]
+        for sc in sorted(self.syscalls,key=lambda x:x["x86id"]):
+            sc_id  = sc["x86id"]
             sc_name = sc["name"]
-            if sc_id != sc_id2 and sc_id2 >= 0 and sc_name not in gen_syscalls:
-                self.gen_NR_syscall( fp, sc_name, sc_id2 )
+            if sc_id >= 0 and sc_name not in gen_syscalls:
+                self.gen_NR_syscall( fp, sc_name, sc_id )
                 gen_syscalls[sc_name] = True
         fp.write( "#endif\n" );
 
+        # all mips-specific syscalls
+        fp.write( "\n#ifdef __mips__\n" );
+        for sc in sorted(self.syscalls,key=lambda x:x["mipsid"]):
+            sc_id = sc["mipsid"]
+            if sc_id >= 0:
+                self.gen_NR_syscall( fp, sc["name"], sc_id )
+        fp.write( "#endif\n" );
+
         fp.write( "\n#endif\n" )
         fp.write( "\n#endif /* _BIONIC_LINUX_SYSCALLS_H_ */\n" );
         fp.close()
@@ -445,6 +470,7 @@
         arch_test = {
             "arm": lambda x: x.has_key("asm-arm") or x.has_key("asm-thumb"),
             "x86": lambda x: x.has_key("asm-x86"),
+            "mips": lambda x: x.has_key("asm-mips")
         }
 
         for sc in self.syscalls:
@@ -454,6 +480,7 @@
         fp.close()
         self.other_files.append( path )
 
+
     # now generate each syscall stub
     def gen_syscall_stubs(self):
         for sc in self.syscalls:
@@ -481,6 +508,13 @@
                 fp.close()
                 self.new_stubs.append( fname )
 
+            if sc.has_key("asm-mips") and 'mips' in all_archs:
+                fname = "arch-mips/syscalls/%s.S" % sc["func"]
+                D2( ">>> generating "+fname )
+                fp = create_file( fname )
+                fp.write(sc["asm-mips"])
+                fp.close()
+                self.new_stubs.append( fname )
 
     def  regenerate(self):
         D( "scanning for existing architecture-specific stub files" )
@@ -498,7 +532,7 @@
 
         if not os.path.exists( bionic_temp ):
             D( "creating %s" % bionic_temp )
-            os.mkdir( bionic_temp )
+            make_dir( bionic_temp )
 
 #        D( "p4 editing source files" )
 #        for arch in all_archs:
diff --git a/libc/tools/zoneinfo/generate b/libc/tools/zoneinfo/generate
index 3e21d0b..ab2617f 100755
--- a/libc/tools/zoneinfo/generate
+++ b/libc/tools/zoneinfo/generate
@@ -1,82 +1,131 @@
-#!/bin/bash
+#!/usr/bin/python
 # Run with no arguments from any directory, with no special setup required.
 
-# Abort if any command returns an error exit status, or if an undefined
-# variable is used.
-set -e
-set -u
+import ftplib
+import hashlib
+import os
+import re
+import shutil
+import string
+import subprocess
+import sys
+import tarfile
+import tempfile
 
-echo "Looking for bionic..."
-bionic_dir=$(cd $(dirname $0)/../../.. && pwd)
-bionic_zoneinfo_dir=$bionic_dir/libc/zoneinfo
-bionic_zoneinfo_tools_dir=$bionic_dir/libc/tools/zoneinfo
-if [[ ! -d "$bionic_zoneinfo_dir" || ! -d "$bionic_zoneinfo_tools_dir" ]]; then
-  echo "Can't find bionic's zoneinfo directories!"
-  exit 1
-fi
+# Find the bionic directory, searching upward from this script.
+bionic_libc_tools_zoneinfo_dir = os.path.realpath(os.path.dirname(sys.argv[0]))
+bionic_libc_tools_dir = os.path.dirname(bionic_libc_tools_zoneinfo_dir)
+bionic_libc_dir = os.path.dirname(bionic_libc_tools_dir)
+bionic_dir = os.path.dirname(bionic_libc_dir)
+bionic_libc_zoneinfo_dir = '%s/libc/zoneinfo' % bionic_dir
+if not os.path.isdir(bionic_libc_tools_zoneinfo_dir) or not os.path.isdir(bionic_libc_zoneinfo_dir):
+  print "Couldn't find bionic/libc/tools/zoneinfo!"
+  sys.exit(1)
+print 'Found bionic in %s...' % bionic_dir
 
-echo "Switching to temporary directory..."
-temp_dir=`mktemp -d`
-cd $temp_dir
-trap "rm -rf $temp_dir; exit" INT TERM EXIT
+
+regions = ['africa', 'antarctica', 'asia', 'australasia', 'backward', 'etcetera', 'europe', 'northamerica', 'southamerica']
+
+
+def current_tzdata_version():
+  return open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir).readline().rstrip('\n')
+
+
+def md5_file(filename):
+  md5 = hashlib.md5()
+  f = open(filename, 'rb')
+  while True:
+    data = f.read(8192)
+    if not data:
+      break
+    md5.update(data)
+  return md5.hexdigest()
+
+
+def upgrade_to(ftp, filename):
+  version = re.search('tzdata(.+)\.tar\.gz', filename).group(1)
+
+  # Switch to a temporary directory.
+  tmp_dir = tempfile.mkdtemp('-tzdata')
+  os.chdir(tmp_dir)
+  print 'Created temporary directory "%s"...' % tmp_dir
+
+  print 'Downloading %s...' % filename
+  ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
+  print 'MD5: %s' % md5_file(filename)
+
+  print 'Extracting...'
+  os.mkdir('extracted')
+  tar = tarfile.open(filename, 'r')
+  tar.extractall('extracted')
+
+  print 'Calling zic(1)...'
+  os.mkdir('data')
+  for region in regions:
+    if region != 'backward':
+      subprocess.check_call(['zic', '-d', 'data', 'extracted/%s' % region])
+
+  # Collect the data ZoneCompactor needs.
+  links = []
+  zones = []
+  for region in regions:
+    for line in open('extracted/%s' % region).readlines():
+      fields = string.split(line)
+      if len(fields) == 0:
+        continue
+      elif fields[0] == 'Link':
+        links.append('%s %s %s\n' % (fields[0], fields[1], fields[2]))
+        zones.append(fields[2])
+      elif fields[0] == 'Zone':
+        zones.append(fields[1])
+  zones.sort()
+
+  # Write it into the "setup" file.
+  setup = open('setup', 'w')
+  for link in links:
+    setup.write(link)
+  for zone in zones:
+    setup.write('%s\n' % zone)
+  setup.close()
+
+  print 'Calling ZoneCompactor...'
+  subprocess.check_call(['javac', '-d', '.',
+                         '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir,
+                         '%s/ZoneInfo.java' % bionic_libc_tools_zoneinfo_dir])
+  subprocess.check_call(['java', 'ZoneCompactor', 'setup', 'data'])
+
+  print 'Updating bionic from %s to %s...' % (current_tzdata_version(), version)
+  # Move the .dat and .idx files...
+  os.remove('%s/zoneinfo.dat' % bionic_libc_zoneinfo_dir)
+  shutil.move('zoneinfo.dat', bionic_libc_zoneinfo_dir)
+  os.remove('%s/zoneinfo.idx' % bionic_libc_zoneinfo_dir)
+  shutil.move('zoneinfo.idx', bionic_libc_zoneinfo_dir)
+  # Write the .version file...
+  zoneinfo_version = open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir, 'wb+')
+  zoneinfo_version.write('%s\n' % version)
+  zoneinfo_version.close()
+
 
 # URL from "Sources for Time Zone and Daylight Saving Time Data"
 # http://www.twinsun.com/tz/tz-link.htm
-echo "Looking for new tzdata..."
-wget -N --no-verbose 'ftp://munnari.oz.au/pub/tzdata*.tar.gz'
-zoneinfo_version_file=$bionic_zoneinfo_dir/zoneinfo.version
-if [ -f "$zoneinfo_version_file" ]; then
-  current_version=tzdata`sed s/\n// < $zoneinfo_version_file`
-else
-  current_version=missing
-fi
-latest_archive=`ls -r -v tzdata*.tar.gz | head -n1`
-latest_version=`basename $latest_archive .tar.gz`
-if [ "$current_version" == "$latest_version" ]; then
-  echo "You already have the latest tzdata ($latest_version)!"
-  exit 1
-fi
 
-md5_sum=`md5sum $latest_archive`
-echo "MD5: $md5_sum"
+print 'Looking for new tzdata...'
+ftp = ftplib.FTP('ftp.iana.org')
+ftp.login()
+ftp.cwd('tz/releases')
+tzdata_filenames = []
+for filename in ftp.nlst():
+  if filename.startswith('tzdata20'):
+    tzdata_filenames.append(filename)
+tzdata_filenames.sort()
 
-echo "Extracting $latest_version..."
-mkdir $latest_version
-tar -C $latest_version -zxf $latest_archive
+# If you're several releases behind, we'll walk you through the upgrades one by one.
+current_version = current_tzdata_version()
+current_filename = 'tzdata%s.tar.gz' % current_version
+for filename in tzdata_filenames:
+  if filename > current_filename:
+    upgrade_to(ftp, filename)
+    sys.exit(0)
 
-echo "Compiling $latest_version..."
-mkdir data
-for i in \
-    africa \
-    antarctica \
-    asia \
-    australasia \
-    etcetera \
-    europe \
-    factory \
-    northamerica \
-    solar87 \
-    solar88 \
-    solar89 \
-    southamerica
-do
-    zic -d data $latest_version/$i
-done
-
-echo "Compacting $latest_version..."
-(
-    cat $latest_version/* | grep '^Link' | awk '{print $1, $2, $3}'
-    (
-        cat $latest_version/* | grep '^Zone' | awk '{print $2}'
-        cat $latest_version/* | grep '^Link' | awk '{print $3}'
-    ) | LC_ALL="C" sort
-) | grep -v Riyadh8 > setup
-
-javac -d . \
-    $bionic_zoneinfo_tools_dir/ZoneCompactor.java \
-    $bionic_zoneinfo_tools_dir/ZoneInfo.java
-java ZoneCompactor setup data
-
-echo "Updating bionic to $latest_version..."
-mv zoneinfo.dat zoneinfo.idx $bionic_zoneinfo_dir
-echo $latest_version | sed 's/tzdata//' > $bionic_zoneinfo_dir/zoneinfo.version
+print 'You already have the latest tzdata (%s)!' % current_version
+sys.exit(0)
diff --git a/libc/unistd/abort.c b/libc/unistd/abort.c
index a3f8c54..4dffbae 100644
--- a/libc/unistd/abort.c
+++ b/libc/unistd/abort.c
@@ -34,11 +34,6 @@
 #include "thread_private.h"
 #include "atexit.h"
 
-/* temporary, for bug hunting */
-#include "logd.h"
-#define debug_log(format, ...)  \
-    __libc_android_log_print(ANDROID_LOG_DEBUG, "libc-abort", (format), ##__VA_ARGS__ )
-
 #ifdef __arm__
 __LIBC_HIDDEN__ void
 __libc_android_abort(void)
@@ -51,7 +46,7 @@
 	static int cleanup_called = 0;
 	sigset_t mask;
 
-  
+
 	sigfillset(&mask);
 	/*
 	 * don't block SIGABRT to give any handler a chance; we ignore
@@ -79,7 +74,12 @@
 
     /* temporary, for bug hunting */
     /* seg fault seems to produce better debuggerd results than SIGABRT */
+#ifdef __mips__
+    /* An access that will generate SIGSEGV rather than SIGBUS. */
+    *((char*)0xdeadc0c0) = 39;
+#else
     *((char*)0xdeadbaad) = 39;
+#endif
     /* -- */
 
 	(void)kill(getpid(), SIGABRT);
diff --git a/libc/unistd/open.c b/libc/unistd/open.c
index 03cba45..56602db 100644
--- a/libc/unistd/open.c
+++ b/libc/unistd/open.c
@@ -28,6 +28,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdarg.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
 extern int  __open(const char*, int, int);
 
@@ -49,3 +51,15 @@
     return __open(pathname, flags, mode);
 }
 
+int __open_2(const char *pathname, int flags) {
+    if (flags & O_CREAT) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** open(O_CREAT) called without specifying a mode ***\n");
+        abort();
+    }
+
+    flags |= O_LARGEFILE;
+
+    return __open(pathname, flags, 0);
+}
+
diff --git a/libc/unistd/openat.c b/libc/unistd/openat.c
index 6b7b367..fb04e9c 100644
--- a/libc/unistd/openat.c
+++ b/libc/unistd/openat.c
@@ -28,6 +28,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdarg.h>
+#include <stdlib.h>
+#include <private/logd.h>
 
 extern int  __openat(int, const char*, int, int);
 
@@ -49,3 +51,16 @@
     return __openat(fd, pathname, flags, mode);
 }
 
+int __openat_2(int fd, const char *pathname, int flags)
+{
+    if (flags & O_CREAT) {
+        __libc_android_log_print(ANDROID_LOG_FATAL, "libc",
+            "*** openat(O_CREAT) called without specifying a mode ***\n");
+        abort();
+    }
+
+    flags |= O_LARGEFILE;
+
+    return __openat(fd, pathname, flags, 0);
+}
+
diff --git a/libc/unistd/sysconf.c b/libc/unistd/sysconf.c
index 9377802..7caa4e9 100644
--- a/libc/unistd/sysconf.c
+++ b/libc/unistd/sysconf.c
@@ -25,16 +25,19 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <unistd.h>
-#include <sys/sysconf.h>
-#include <limits.h>
-#include <bionic_tls.h>
+
 #include <asm/page.h>
-#include <stdio.h>  /* for FOPEN_MAX */
+#include <bionic_tls.h>
+#include <ctype.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>  // For FOPEN_MAX.
 #include <string.h>
-#include <ctype.h>
+#include <sys/sysconf.h>
+#include <unistd.h>
 
 /* seems to be the default on Linux, per the GLibc sources and my own digging */
 
@@ -62,18 +65,88 @@
 #define  SYSTEM_2_FORT_DEV   -1       /* Fortran development unsupported */
 #define  SYSTEM_2_FORT_RUN   -1       /* Fortran runtime unsupported */
 #define  SYSTEM_2_SW_DEV     -1       /* posix software dev utilities unsupported */
-#define  SYSTEM_2_LOCALEDEF  -1       /* localdef() unimplemented */
+#define  SYSTEM_2_LOCALEDEF  -1       /* localedef() unimplemented */
 #define  SYSTEM_2_UPE        -1       /* No UPE for you ! (User Portability Utilities) */
 #define  SYSTEM_2_VERSION    -1       /* No posix command-line tools */
 
-static int  __get_nproc_conf(void);
-static int  __get_nproc_onln(void);
-static int  __get_phys_pages(void);
-static int  __get_avphys_pages(void);
+static bool __matches_cpuN(const char* s) {
+  // The %c trick is to ensure that we have the anchored match "^cpu[0-9]+$".
+  unsigned cpu;
+  char dummy;
+  return (sscanf(s, "cpu%u%c", &cpu, &dummy) == 1);
+}
 
-int
-sysconf( int  name )
-{
+static int __get_nproc_conf(void) {
+  // On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
+  // from there. This method works on both.
+  DIR* d = opendir("/sys/devices/system/cpu");
+  if (!d) {
+    return 1;
+  }
+
+  int result = 0;
+  struct dirent de;
+  struct dirent* e;
+  while (!readdir_r(d, &de, &e) && e != NULL) {
+    if (e->d_type == DT_DIR && __matches_cpuN(e->d_name)) {
+      ++result;
+    }
+  }
+  closedir(d);
+  return result;
+}
+
+static int __get_nproc_onln(void) {
+  FILE* fp = fopen("/proc/stat", "r");
+  if (fp == NULL) {
+    return 1;
+  }
+
+  int result = 0;
+  char buf[256];
+  while (fgets(buf, sizeof(buf), fp) != NULL) {
+    // Extract just the first word from the line.
+    // 'cpu0 7976751 1364388 3116842 469770388 8629405 0 49047 0 0 0'
+    char* p = strchr(buf, ' ');
+    if (p != NULL) {
+      *p = 0;
+    }
+    if (__matches_cpuN(buf)) {
+      ++result;
+    }
+  }
+  fclose(fp);
+  return result;
+}
+
+static int __get_meminfo(const char* pattern) {
+  FILE* fp = fopen("/proc/meminfo", "r");
+  if (fp == NULL) {
+    return -1;
+  }
+
+  int result = -1;
+  char buf[256];
+  while (fgets(buf, sizeof(buf), fp) != NULL) {
+    long total;
+    if (sscanf(buf, pattern, &total) == 1) {
+      result = (int) (total / (PAGE_SIZE/1024));
+      break;
+    }
+  }
+  fclose(fp);
+  return result;
+}
+
+static int __get_phys_pages(void) {
+  return __get_meminfo("MemTotal: %ld kB");
+}
+
+static int __get_avphys_pages(void) {
+  return __get_meminfo("MemFree: %ld kB");
+}
+
+int sysconf(int name) {
     switch (name) {
 #ifdef _POSIX_ARG_MAX
     case _SC_ARG_MAX:           return _POSIX_ARG_MAX;
@@ -266,169 +339,3 @@
         return -1;
     }
 }
-
-
-typedef struct {
-    int   rpos;
-    int   len;
-    int   overflow;
-    int   fd;
-    int   in_len;
-    int   in_pos;
-    char  buff[128];
-    char  input[128];
-} LineParser;
-
-static int
-line_parser_init( LineParser*  p, const char*  path )
-{
-    p->rpos     = 0;
-    p->len      = (int)sizeof(p->buff);
-    p->overflow = 0;
-
-    p->in_len   = 0;
-    p->in_pos   = 0;
-    p->fd       = open( path, O_RDONLY );
-
-    return p->fd;
-}
-
-
-static int
-line_parser_addc( LineParser*  p, int  c )
-{
-    if (p->overflow) {
-        p->overflow = (c == '\n');
-        return 0;
-    }
-    if (p->rpos >= p->len) {
-        p->overflow = 1;
-        return 0;
-    }
-    if (c == '\n') {
-        p->buff[p->rpos] = 0;
-        p->rpos = 0;
-        return 1;
-    }
-    p->buff[p->rpos++] = (char) c;
-    return 0;
-}
-
-static int
-line_parser_getc( LineParser*  p )
-{
-    if (p->in_pos >= p->in_len) {
-        int  ret;
-
-        p->in_len = p->in_pos = 0;
-        do {
-            ret = read(p->fd, p->input, sizeof(p->input));
-        } while (ret < 0 && errno == EINTR);
-
-        if (ret <= 0)
-            return -1;
-
-        p->in_len = ret;
-    }
-    return p->input[ p->in_pos++ ];
-}
-
-static const char*
-line_parser_gets( LineParser*  p )
-{
-    for (;;) {
-        for (;;) {
-            int  c = line_parser_getc(p);
-
-            if (c < 0) {
-                close(p->fd);
-                p->fd = -1;
-                return NULL;
-             }
-             if (line_parser_addc(p, c))
-                return p->buff;
-        }
-    }
-}
-
-static void
-line_parser_done( LineParser* p )
-{
-    if (p->fd >= 0) {
-        close(p->fd);
-        p->fd = -1;
-    }
-}
-
-static int
-__get_nproc_conf(void)
-{
-    LineParser   parser[1];
-    const char*  p;
-    int          count = 0;
-
-    if (line_parser_init(parser, "/proc/cpuinfo") < 0)
-        return 1;
-
-    while ((p = line_parser_gets(parser))) {
-        if ( !memcmp(p, "processor", 9) )
-            count += 1;
-    }
-    return (count < 1) ? 1 : count;
-}
-
-
-static int
-__get_nproc_onln(void)
-{
-    LineParser   parser[1];
-    const char*  p;
-    int          count = 0;
-
-    if (line_parser_init(parser, "/proc/stat") < 0)
-        return 1;
-
-    while ((p = line_parser_gets(parser))) {
-        if ( !memcmp(p, "cpu", 3) && isdigit(p[3]) )
-            count += 1;
-    }
-    return (count < 1) ? 1 : count;
-}
-
-static int
-__get_phys_pages(void)
-{
-    LineParser   parser[1];
-    const char*  p;
-
-    if (line_parser_init(parser, "/proc/meminfo") < 0)
-        return -2;  /* what ? */
-
-    while ((p = line_parser_gets(parser))) {
-        long  total;
-        if ( sscanf(p, "MemTotal: %ld kB", &total) == 1 ) {
-            line_parser_done(parser);
-            return (int) (total / (PAGE_SIZE/1024));
-        }
-    }
-    return -3;
-}
-
-static int
-__get_avphys_pages(void)
-{
-    LineParser   parser[1];
-    const char*  p;
-
-    if (line_parser_init(parser, "/proc/meminfo") < 0)
-        return -1;  /* what ? */
-
-    while ((p = line_parser_gets(parser))) {
-        long  total;
-        if ( sscanf(p, "MemFree: %ld kB", &total) == 1 ) {
-            line_parser_done(parser);
-            return (int) (total / (PAGE_SIZE/1024));
-        }
-    }
-    return -1;
-}
diff --git a/libc/zoneinfo/Android.mk b/libc/zoneinfo/Android.mk
index ef700e8..716aab2 100644
--- a/libc/zoneinfo/Android.mk
+++ b/libc/zoneinfo/Android.mk
@@ -1,26 +1,67 @@
 LOCAL_PATH:= $(call my-dir)
+
+############################################
 include $(CLEAR_VARS)
+LOCAL_MODULE := zoneinfo.dat
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/zoneinfo
+include $(BUILD_PREBUILT)
 
-ALL_PREBUILT += $(TARGET_OUT)/usr/share/zoneinfo/zoneinfo.dat
-$(TARGET_OUT)/usr/share/zoneinfo/zoneinfo.dat : $(LOCAL_PATH)/zoneinfo.dat | $(ACP)
-	$(transform-prebuilt-to-target)
+############################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := zoneinfo.idx
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/zoneinfo
+include $(BUILD_PREBUILT)
 
-ALL_PREBUILT += $(TARGET_OUT)/usr/share/zoneinfo/zoneinfo.idx
-$(TARGET_OUT)/usr/share/zoneinfo/zoneinfo.idx : $(LOCAL_PATH)/zoneinfo.idx | $(ACP)
-	$(transform-prebuilt-to-target)
+############################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := zoneinfo.version
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/zoneinfo
+include $(BUILD_PREBUILT)
 
-ALL_PREBUILT += $(TARGET_OUT)/usr/share/zoneinfo/zoneinfo.version
-$(TARGET_OUT)/usr/share/zoneinfo/zoneinfo.version : $(LOCAL_PATH)/zoneinfo.version | $(ACP)
-	$(transform-prebuilt-to-target)
 
 # The host build doesn't use bionic, but it does use bionic's zoneinfo data
 ifeq ($(WITH_HOST_DALVIK),true)
-    ALL_PREBUILT += $(HOST_OUT)/usr/share/zoneinfo/zoneinfo.dat
-    $(eval $(call copy-one-file,$(LOCAL_PATH)/zoneinfo.dat,$(HOST_OUT)/usr/share/zoneinfo/zoneinfo.dat))
 
-    ALL_PREBUILT += $(HOST_OUT)/usr/share/zoneinfo/zoneinfo.idx
-    $(eval $(call copy-one-file,$(LOCAL_PATH)/zoneinfo.idx,$(HOST_OUT)/usr/share/zoneinfo/zoneinfo.idx))
+############################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := zoneinfo-host.dat
+LOCAL_IS_HOST_MODULE := true
+LOCAL_SRC_FILES := zoneinfo.dat
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_STEM := $(LOCAL_SRC_FILES)
+LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share/zoneinfo
+include $(BUILD_PREBUILT)
 
-    ALL_PREBUILT += $(HOST_OUT)/usr/share/zoneinfo/zoneinfo.version
-    $(eval $(call copy-one-file,$(LOCAL_PATH)/zoneinfo.version,$(HOST_OUT)/usr/share/zoneinfo/zoneinfo.version))
+############################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := zoneinfo-host.idx
+LOCAL_IS_HOST_MODULE := true
+LOCAL_SRC_FILES := zoneinfo.idx
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_STEM := $(LOCAL_SRC_FILES)
+LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share/zoneinfo
+include $(BUILD_PREBUILT)
+
+############################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := zoneinfo-host.version
+LOCAL_IS_HOST_MODULE := true
+LOCAL_SRC_FILES := zoneinfo.version
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_STEM := $(LOCAL_SRC_FILES)
+LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share/zoneinfo
+include $(BUILD_PREBUILT)
+
 endif
diff --git a/libc/zoneinfo/zoneinfo.dat b/libc/zoneinfo/zoneinfo.dat
index cc1cb38..82d6b9c 100644
--- a/libc/zoneinfo/zoneinfo.dat
+++ b/libc/zoneinfo/zoneinfo.dat
Binary files differ
diff --git a/libc/zoneinfo/zoneinfo.idx b/libc/zoneinfo/zoneinfo.idx
index 0483c28..2268706 100644
--- a/libc/zoneinfo/zoneinfo.idx
+++ b/libc/zoneinfo/zoneinfo.idx
Binary files differ
diff --git a/libc/zoneinfo/zoneinfo.version b/libc/zoneinfo/zoneinfo.version
index 9412b94..e606761 100644
--- a/libc/zoneinfo/zoneinfo.version
+++ b/libc/zoneinfo/zoneinfo.version
@@ -1 +1 @@
-2012c
+2012d
diff --git a/libdl/Android.mk b/libdl/Android.mk
index d2289f8..fb01ec2 100644
--- a/libdl/Android.mk
+++ b/libdl/Android.mk
@@ -34,21 +34,6 @@
 LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
 LOCAL_SYSTEM_SHARED_LIBRARIES := 
 
-ifeq ($(TARGET_ARCH),sh)
-# for SuperH, additional code is necessary to handle .ctors section.
-GEN_SOBEGIN := $(TARGET_OUT_STATIC_LIBRARIES)/sobegin.o
-$(GEN_SOBEGIN): $(LOCAL_PATH)/arch-sh/sobegin.S
-	@mkdir -p $(dir $@)
-	$(TARGET_CC) -o $@ -c $<
-
-GEN_SOEND := $(TARGET_OUT_STATIC_LIBRARIES)/soend.o
-$(GEN_SOEND): $(LOCAL_PATH)/arch-sh/soend.S
-	@mkdir -p $(dir $@)
-	$(TARGET_CC) -o $@ -c $<
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GEN_SOBEGIN) $(GEN_SOEND)
-endif
-
 include $(BUILD_SHARED_LIBRARY)
 
 BUILD_DLTEST:=0
diff --git a/libdl/arch-sh/sobegin.S b/libdl/arch-sh/sobegin.S
deleted file mode 100644
index 976b1a6..0000000
--- a/libdl/arch-sh/sobegin.S
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-    .text
-    .align 4
-    .type  _init,#function
-    .globl _init
-
-# The toolchain for SH-Linux does not produce INIT_ARRAY information which
-# bionic linker relies on.  Instead of it, The toolchain for SH-Linux produces
-# INIT information when it find the function whose name is '_init'.
-#
-_init:
-    sts.l   pr, @-r15
-    mov.l   r8, @-r15
-    mov.l   0f, r8      /* first entry is invalid */
-.L_loop:
-    add     #4, r8
-    mov.l   @r8, r0
-    cmp/eq  #0, r0      /* Zero terimnated. See 'soend.so'. */
-    bt      .L_end
-    jsr     @r0         /* invoke a constructor */
-    nop
-    bra     .L_loop
-    nop
-.L_end:
-    mov.l   @r15+, r8
-    lds.l   @r15+, pr
-
-    rts
-    nop
-
-    .balign 4
-0:  .long   __CTOR_LIST__
-
-# the .ctors section contains a list of pointers to "constructor"
-# functions that need to be called in order during C library initialization,
-# just before the program is being run. This is a C++ requirement
-#
-# the last entry shall be 0, and is defined in crtend.S
-#
-    .section .ctors, "aw"
-    .globl __CTOR_LIST__
-__CTOR_LIST__:
-    .long   -1
-
diff --git a/libdl/libdl.c b/libdl/libdl.c
index 872c0c9..1d51c37 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.c
@@ -26,11 +26,11 @@
 
 #ifdef __arm__
 void *dl_unwind_find_exidx(void *pc, int *pcount) { return 0; }
-#elif defined(__i386__) || defined(__sh__)
+#elif defined(__i386__) || defined(__sh__) || defined(__mips__)
 /* we munge the cb definition so we don't have to include any headers here.
  * It won't affect anything since these are just symbols anyway */
 int dl_iterate_phdr(int (*cb)(void *info, void *size, void *data),
                     void *data) { return 0; }
 #else
-#error Unsupported architecture. Only arm and x86 are supported.
+#error Unsupported architecture. Only mips, arm and x86 are supported.
 #endif
diff --git a/libm/Android.mk b/libm/Android.mk
index 57e4d4c..756c9ab 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -54,7 +54,6 @@
 	src/e_sinh.c \
 	src/e_sinhf.c \
 	src/e_sqrt.c \
-	src/e_sqrtf.c \
 	src/k_cos.c \
 	src/k_cosf.c \
 	src/k_rem_pio2.c \
@@ -152,6 +151,7 @@
 	src/s_isnan.c \
 	src/s_modf.c
 
+libm_common_cflags :=
 
 ifeq ($(TARGET_ARCH),arm)
   libm_common_src_files += \
@@ -159,24 +159,35 @@
 	src/e_ldexpf.c \
 	src/s_scalbln.c \
 	src/s_scalbn.c \
-	src/s_scalbnf.c
+	src/s_scalbnf.c \
+	src/e_sqrtf.c
 
   libm_common_includes = $(LOCAL_PATH)/arm
+endif
 
-else
-  ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
-    libm_common_src_files += \
+ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
+  libm_common_src_files += \
 	i387/fenv.c \
 	i387/s_scalbnl.S \
 	i387/s_scalbn.S \
-	i387/s_scalbnf.S
+	i387/s_scalbnf.S \
+	i387/e_sqrtf.S
 
-    libm_common_includes = $(LOCAL_PATH)/i386 $(LOCAL_PATH)/i387
-  else
-    $(error "Unknown architecture")
-  endif
+  libm_common_includes = $(LOCAL_PATH)/i386 $(LOCAL_PATH)/i387
 endif
+ifeq ($(TARGET_ARCH),mips)
+  libm_common_src_files += \
+	mips/fenv.c \
+	src/e_ldexpf.c \
+	src/s_scalbln.c \
+	src/s_scalbn.c \
+	src/s_scalbnf.c \
+	src/e_sqrtf.c
 
+  libm_common_includes = $(LOCAL_PATH)/mips
+  # Need to build *rint* functions
+  libm_common_cflags += -fno-builtin-rintf -fno-builtin-rint
+endif
 
 # libm.a
 # ========================================================
@@ -188,6 +199,7 @@
 
 LOCAL_ARM_MODE := arm
 LOCAL_C_INCLUDES += $(libm_common_includes)
+LOCAL_CFLAGS := $(libm_common_cflags)
 
 LOCAL_MODULE:= libm
 
@@ -206,6 +218,7 @@
 LOCAL_ARM_MODE := arm
 
 LOCAL_C_INCLUDES += $(libm_common_includes)
+LOCAL_CFLAGS := $(libm_common_cflags)
 
 LOCAL_MODULE:= libm
 
diff --git a/libm/mips/Makefile.inc b/libm/mips/Makefile.inc
new file mode 100644
index 0000000..9bbfaa1
--- /dev/null
+++ b/libm/mips/Makefile.inc
@@ -0,0 +1,3 @@
+# $FreeBSD: src/lib/msun/mips/Makefile.inc,v 1.1 2008/04/26 12:20:29 imp Exp $
+
+LDBL_PREC = 53
diff --git a/libm/mips/_fpmath.h b/libm/mips/_fpmath.h
new file mode 100644
index 0000000..cb6e8c0
--- /dev/null
+++ b/libm/mips/_fpmath.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/mips/_fpmath.h,v 1.1 2008/04/26 12:07:59 imp Exp $
+ */
+
+union IEEEl2bits {
+	long double	e;
+	struct {
+#ifndef __MIPSEB__
+		unsigned int	manl	:32;
+		unsigned int	manh	:20;
+		unsigned int	exp	:11;
+		unsigned int	sign	:1;
+#else
+		unsigned int		sign	:1;
+		unsigned int		exp	:11;
+		unsigned int		manh	:20;
+		unsigned int		manl	:32;
+#endif
+	} bits;
+};
+
+#define	LDBL_NBIT	0
+#define	mask_nbit_l(u)	((void)0)
+#define	LDBL_IMPLICIT_NBIT
+
+#define	LDBL_MANH_SIZE	20
+#define	LDBL_MANL_SIZE	32
+
+#define	LDBL_TO_ARRAY32(u, a) do {			\
+	(a)[0] = (uint32_t)(u).bits.manl;		\
+	(a)[1] = (uint32_t)(u).bits.manh;		\
+} while(0)
diff --git a/libm/mips/fenv.c b/libm/mips/fenv.c
new file mode 100644
index 0000000..b5f52da
--- /dev/null
+++ b/libm/mips/fenv.c
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/mips/fenv.c,v 1.1 2008/04/26 12:20:29 imp Exp $
+ */
+
+#include <fenv.h>
+
+/*
+ * Hopefully the system ID byte is immutable, so it's valid to use
+ * this as a default environment.
+ */
+const fenv_t __fe_dfl_env = 0;
diff --git a/libm/mips/fenv.h b/libm/mips/fenv.h
new file mode 100644
index 0000000..061a696
--- /dev/null
+++ b/libm/mips/fenv.h
@@ -0,0 +1,218 @@
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/mips/fenv.h,v 1.1 2008/04/26 12:20:29 imp Exp $
+ */
+
+#ifndef	_FENV_H_
+#define	_FENV_H_
+
+#include <sys/_types.h>
+
+typedef	__uint32_t	fenv_t;
+typedef	__uint32_t	fexcept_t;
+
+/* Exception flags */
+#define	FE_INVALID	0x0001
+#define	FE_DIVBYZERO	0x0002
+#define	FE_OVERFLOW	0x0004
+#define	FE_UNDERFLOW	0x0008
+#define	FE_INEXACT	0x0010
+#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
+			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/* Rounding modes */
+#define	FE_TONEAREST	0x0000
+#define	FE_TOWARDZERO	0x0001
+#define	FE_UPWARD	0x0002
+#define	FE_DOWNWARD	0x0003
+#define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
+			 FE_UPWARD | FE_TOWARDZERO)
+/* __BEGIN_DECLS */
+
+/* Default floating-point environment */
+extern const fenv_t	__fe_dfl_env;
+#define	FE_DFL_ENV	(&__fe_dfl_env)
+
+/* We need to be able to map status flag positions to mask flag positions */
+#define _FPUSW_SHIFT	16
+#define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
+
+#ifdef	ARM_HARD_FLOAT
+#define	__rfs(__fpsr)	__asm __volatile("rfs %0" : "=r" (*(__fpsr)))
+#define	__wfs(__fpsr)	__asm __volatile("wfs %0" : : "r" (__fpsr))
+#else
+#define __rfs(__fpsr)
+#define __wfs(__fpsr)
+#endif
+
+static __inline int
+feclearexcept(int __excepts)
+{
+	fexcept_t __fpsr;
+
+	__rfs(&__fpsr);
+	__fpsr &= ~__excepts;
+	__wfs(__fpsr);
+	return (0);
+}
+
+static __inline int
+fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+	fexcept_t __fpsr;
+
+	__rfs(&__fpsr);
+	*__flagp = __fpsr & __excepts;
+	return (0);
+}
+
+static __inline int
+fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+{
+	fexcept_t __fpsr;
+
+	__rfs(&__fpsr);
+	__fpsr &= ~__excepts;
+	__fpsr |= *__flagp & __excepts;
+	__wfs(__fpsr);
+	return (0);
+}
+
+static __inline int
+feraiseexcept(int __excepts)
+{
+	fexcept_t __ex = __excepts;
+
+	fesetexceptflag(&__ex, __excepts);	/* XXX */
+	return (0);
+}
+
+static __inline int
+fetestexcept(int __excepts)
+{
+	fexcept_t __fpsr;
+
+	__rfs(&__fpsr);
+	return (__fpsr & __excepts);
+}
+
+static __inline int
+fegetround(void)
+{
+
+	/*
+	 * Apparently, the rounding mode is specified as part of the
+	 * instruction format on ARM, so the dynamic rounding mode is
+	 * indeterminate.  Some FPUs may differ.
+	 */
+	return (-1);
+}
+
+static __inline int
+fesetround(int __round)
+{
+
+	return (-1);
+}
+
+static __inline int
+fegetenv(fenv_t *__envp)
+{
+
+	__rfs(__envp);
+	return (0);
+}
+
+static __inline int
+feholdexcept(fenv_t *__envp)
+{
+	fenv_t __env;
+
+	__rfs(&__env);
+	*__envp = __env;
+	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
+	__wfs(__env);
+	return (0);
+}
+
+static __inline int
+fesetenv(const fenv_t *__envp)
+{
+
+	__wfs(*__envp);
+	return (0);
+}
+
+static __inline int
+feupdateenv(const fenv_t *__envp)
+{
+	fexcept_t __fpsr;
+
+	__rfs(&__fpsr);
+	__wfs(*__envp);
+	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
+	return (0);
+}
+
+#if __BSD_VISIBLE
+
+static __inline int
+feenableexcept(int __mask)
+{
+	fenv_t __old_fpsr, __new_fpsr;
+
+	__rfs(&__old_fpsr);
+	__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
+	__wfs(__new_fpsr);
+	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static __inline int
+fedisableexcept(int __mask)
+{
+	fenv_t __old_fpsr, __new_fpsr;
+
+	__rfs(&__old_fpsr);
+	__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
+	__wfs(__new_fpsr);
+	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static __inline int
+fegetexcept(void)
+{
+	fenv_t __fpsr;
+
+	__rfs(&__fpsr);
+	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
+}
+
+#endif /* __BSD_VISIBLE */
+
+/* __END_DECLS */
+
+#endif	/* !_FENV_H_ */
+
diff --git a/libm/sh/_fpmath.h b/libm/sh/_fpmath.h
deleted file mode 100644
index f75ec7b..0000000
--- a/libm/sh/_fpmath.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2009 Android Open Source Project, All rights reserved.
- *   Derived from "bionic/libm/arm/_fpmath.h"
- *   Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Assumes that 'long double' on SH-linux is just an alias for 'double'.
- */
-union IEEEl2bits {
-	long double	e;
-	struct {
-#if  __BYTE_ORDER == __LITTLE_ENDIAN
-		unsigned int	manl	:32;
-		unsigned int	manh	:20;
-		unsigned int	exp	:11;
-		unsigned int	sign	:1;
-#elif __BYTE_ORDER == __BIG_ENDIAN
-		unsigned int	sign	:1;
-		unsigned int	exp	:11;
-		unsigned int	manh	:20;
-		unsigned int	manl	:32;
-#endif
-	} bits;
-};
-
-/*
- * LDBL_NBIT is a mask indicating the position of the integer
- * bit in a long double.  But SH4 does not support it.
- */
-#define	LDBL_NBIT	0
-#define	mask_nbit_l(u)	((void)0)
-
-#define	LDBL_MANH_SIZE	20
-#define	LDBL_MANL_SIZE	32
diff --git a/libm/sh/fenv.c b/libm/sh/fenv.c
deleted file mode 100644
index ca8f476..0000000
--- a/libm/sh/fenv.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2009 Android Open Source Project, All rights reserved.
- *   Derived from "bionic/libm/arm/fenv.c"
- *   Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-long __fpscr_values[2] = { 0L, 0x80000L };
diff --git a/libm/sh/fenv.h b/libm/sh/fenv.h
deleted file mode 100644
index e872f47..0000000
--- a/libm/sh/fenv.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2009 Android Open Source Project, All rights reserved.
- *   Derived from "bionic/libm/arm/fenv.h"
- *   Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _FENV_H_
-#define _FENV_H_
-
-#include <stdio.h>
-#include <sys/types.h>
-
-typedef	uint32_t	fenv_t;
-typedef	uint32_t	fexcept_t;
-
-/* Exception flags */
-#define	FE_INVALID		0x0010
-#define	FE_DIVBYZERO	0x0008
-#define	FE_OVERFLOW		0x0004
-#define	FE_UNDERFLOW	0x0002
-#define	FE_INEXACT		0x0001
-#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
-				 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
-
-/* Rounding modes */
-#define	FE_TONEAREST	0x0000
-#define	FE_TOWARDZERO	0x0001
-#define	FE_UPWARD	0x0002 /* not supporetd */
-#define	FE_DOWNWARD	0x0003 /* not supporetd */
-#define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
-				 FE_UPWARD | FE_TOWARDZERO)
-
-/* bit shift for FPSCR mapping */
-#define	_FPUE_CAUSE_SHIFT	12
-#define	_FPUE_ENABLE_SHIFT	17
-#define	_FPUE_FLAG_SHIFT	 2
-
-/* bit shifters */
-#define	_FPUE_CAUSE(_EXCS)	((_EXCS) << _FPUE_CAUSE_SHIFT)
-#define	_FPUE_ENABLE(_EXCS)	((_EXCS) << _FPUE_ENABLE_SHIFT)
-#define	_FPUE_FLAG(_EXCS)	((_EXCS) << _FPUE_FLAG_SHIFT)
-
-#define	_GET_FPUE_CAUSE(_FPUE)		(((_FPUE) >> _FPUE_CAUSE_SHIFT) & FE_ALL_EXCEPT)
-#define	_GET_FPUE_ENABLE(_FPUE)	(((_FPUE) >> _FPUE_ENABLE_SHIFT)& FE_ALL_EXCEPT)
-#define	_GET_FPUE_FLAG(_FPUE)		(((_FPUE) >> _FPUE_FLAG_SHIFT) & FE_ALL_EXCEPT)
-
-
-/* FPSCR register accessors */
-#ifdef	__SH4_NOFPU__
-#define	__read_fpscr(_ptr)
-#define	__write_fpscr(_val)
-#else
-#define	__read_fpscr(_ptr)	__asm __volatile("sts fpscr, %0" : "=r" (*(_ptr)))
-#define	__write_fpscr(_val)	__asm __volatile("lds %0, fpscr" : : "r" (_val))
-#endif
-
-
-/* functions for libm */
-static __inline int
-feclearexcept(int __excepts)
-{
-	uint32_t __fpscr;
-
-	__read_fpscr(&__fpscr);
-	__fpscr &= ~_FPUE_FLAG(__excepts);
-	__write_fpscr(__fpscr);
-	return (0);
-}
-
-static __inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
-{
-	uint32_t __fpscr;
-
-	__read_fpscr(&__fpscr);
-	*__flagp = _GET_FPUE_FLAG(__fpscr) & __excepts;
-	return (0);
-}
-
-
-static __inline int
-fesetexceptflag(const fexcept_t *__flagp, int __excepts)
-{
-	uint32_t __fpscr;
-
-	__read_fpscr(&__fpscr);
-	__fpscr &= ~_FPUE_FLAG(__excepts);
-	__fpscr |= ~_FPUE_FLAG(*__flagp & __excepts);
-	__write_fpscr(__fpscr);
-	return (0);
-}
-
-
-static __inline int
-feraiseexcept(int __excepts)
-{
-	fexcept_t __ex = __excepts;
-
-	fesetexceptflag(&__ex, __excepts);	/* XXX */
-	return (0);
-}
-
-
-static __inline int
-fetestexcept(int __excepts)
-{
-	fexcept_t __ex;
-
-	fegetexceptflag(&__ex,  __excepts);
-	return (__ex);
-}
-
-
-static __inline int
-fegetround(void)
-{
-	uint32_t __fpscr = 0;
-
-	__read_fpscr(&__fpscr);
-	return (__fpscr & _ROUND_MASK);	
-}
-
-static __inline int
-fesetround(int __round)
-{
-	uint32_t __fpscr = 0;
-
-	if (__round == FE_UPWARD || __round == FE_DOWNWARD) {
-		fprintf(stderr, "libm superh : "
-			"upward/downward rounding not supporetd.\n");
-		return -1;
-	}
-
-	__read_fpscr(&__fpscr);
-	__fpscr &= ~_ROUND_MASK;
-	__fpscr |= (__round & _ROUND_MASK);
-	__write_fpscr(__fpscr);
-	return (0);
-}
-
-static __inline int
-fegetenv(fenv_t *__envp)
-{
-	__read_fpscr(__envp);
-	return (0);
-}
-
-static __inline int
-feholdexcept(fenv_t *__envp)
-{
-	uint32_t __fpscr;
-
-	__read_fpscr(&__fpscr);
-	*__envp = __fpscr;
-	__fpscr &= ~_FPUE_FLAG(FE_ALL_EXCEPT);
-	__write_fpscr(__fpscr);
-	return (0);
-}
-
-
-static __inline int
-fesetenv(const fenv_t *__envp)
-{
-	__write_fpscr(*__envp);
-	return (0);
-}
-
-
-static __inline int
-feupdateenv(const fenv_t *__envp)
-{
-	uint32_t __fpscr;
-
-	__read_fpscr(&__fpscr);
-	__write_fpscr(*__envp);
-	feraiseexcept(_GET_FPUE_FLAG(__fpscr));
-	return (0);
-}
-
-#if __BSD_VISIBLE
-
-static __inline int
-feenableexcept(int __mask)
-{
-	uint32_t __old_fpscr, __new_fpscr;
-
-	__read_fpscr(&__old_fpscr);
-	__new_fpscr = __old_fpscr | _FPUE_ENABLE(__mask & FE_ALL_EXCEPT);
-	__write_fpscr(__new_fpscr);
-	return (_GET_FPUE_ENABLE(__old_fpscr));
-}
-
-static __inline int
-fedisableexcept(int __mask)
-{
-	uint32_t __old_fpscr, __new_fpscr;
-
-	__read_fpscr(&__old_fpscr);
-	__new_fpscr = __old_fpscr & ~(_FPUE_ENABLE(__mask & FE_ALL_EXCEPT));
-	__write_fpscr(__new_fpscr);
-	return (_GET_FPUE_ENABLE(__old_fpscr));
-}
-
-static __inline int
-fegetexcept(void)
-{
-	uint32_t __fpscr;
-
-	__read_fpscr(&__fpscr);
-	return (_GET_FPUE_ENABLE(__fpscr));
-}
-
-#endif /* __BSD_VISIBLE */
-
-
-#endif /* _FENV_H_ */
-
diff --git a/libm/src/s_fabsl.c b/libm/src/s_fabsl.c
index 200a9a5..29831d2 100644
--- a/libm/src/s_fabsl.c
+++ b/libm/src/s_fabsl.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 2003 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/msun/src/s_fabsl.c,v 1.2 2003/10/25 19:53:28 des Exp $
+ * $FreeBSD$
  */
 
 #include <math.h>
diff --git a/libstdc++/Android.mk b/libstdc++/Android.mk
index 8bc181f..7d27aa8 100644
--- a/libstdc++/Android.mk
+++ b/libstdc++/Android.mk
@@ -3,7 +3,7 @@
 # Common C++ flags to build this library.
 # Note that we need to access private Bionic headers
 # and define ANDROID_SMP accordingly.
-libstdc++_cflags := -Ibionic/libc/private
+libstdc++_cflags := -Ibionic/libc/
 ifeq ($(TARGET_CPU_SMP),true)
     libstdc++_cflags += -DANDROID_SMP=1
 else
diff --git a/libstdc++/src/one_time_construction.cpp b/libstdc++/src/one_time_construction.cpp
index 1eac3b1..3cfb213 100644
--- a/libstdc++/src/one_time_construction.cpp
+++ b/libstdc++/src/one_time_construction.cpp
@@ -11,8 +11,8 @@
 #include <stddef.h>
 #include <sys/atomics.h>
 #include <endian.h>
-#include <bionic_futex.h>
-#include <bionic_atomic_inline.h>
+#include <private/bionic_futex.h>
+#include <private/bionic_atomic_inline.h>
 
 // ARM C++ ABI and Itanium/x86 C++ ABI has different definition for
 // one time construction:
diff --git a/libstdc++/src/pure_virtual.cpp b/libstdc++/src/pure_virtual.cpp
index 663c1e9..affb80f 100644
--- a/libstdc++/src/pure_virtual.cpp
+++ b/libstdc++/src/pure_virtual.cpp
@@ -1,10 +1,8 @@
+#undef NDEBUG
+#include <assert.h>
 
-#include <stdio.h>
-#include <stdlib.h>
-
-extern "C" void __cxa_pure_virtual()
-{
-    fprintf(stderr, "Pure virtual function called.  Are you calling virtual methods from a destructor?\n");
-    abort();
+extern "C" void __cxa_pure_virtual() {
+  // We can't call __libc_android_log_write from libstdc++ because it's private, so cheat.
+  assert(!"Pure virtual function called. Are you calling virtual methods from a destructor?");
+  /* NOTREACHED */
 }
-
diff --git a/libthread_db/libthread_db.c b/libthread_db/libthread_db.c
index 86e1cf4..e749377 100644
--- a/libthread_db/libthread_db.c
+++ b/libthread_db/libthread_db.c
@@ -99,7 +99,7 @@
         gEventMsgHandle.tid = gEventMsgHandle.pid;
         return 0x42;
     }
-#else
+#elif defined(__arm__)
     pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
 
     if (pc == bkpt_addr) {
@@ -109,6 +109,15 @@
         gEventMsgHandle.tid = gEventMsgHandle.pid;
         return 0x42;
     }
+#elif defined(__mips__)
+    pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)(64*4) /* pc */, NULL);
+    if (pc == bkpt_addr) {
+        // The hook function takes the id of the new thread as it's first param,
+        // so grab it from a0
+        gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)(4*4) /* a0 */, NULL);
+        gEventMsgHandle.tid = gEventMsgHandle.pid;
+        return 0x42;
+    }
 #endif
     return 0;
 }
diff --git a/linker/Android.mk b/linker/Android.mk
index 4a81681..c9d053f 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -6,6 +6,7 @@
 	linker.c \
 	linker_environ.c \
 	linker_format.c \
+	linker_phdr.c \
 	rt.c \
 	dlfcn.c \
 	debugger.c
@@ -14,7 +15,8 @@
 
 LOCAL_CFLAGS += -fno-stack-protector \
         -Wstrict-overflow=5 \
-        -fvisibility=hidden
+        -fvisibility=hidden \
+        -std=gnu99
 
 # Set LINKER_DEBUG to either 1 or 0
 #
@@ -26,7 +28,9 @@
 ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
     LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/../libc/private
+LOCAL_CFLAGS += \
+    -I$(LOCAL_PATH)/../libc/private \
+    -I$(LOCAL_PATH)/../libc/arch-$(TARGET_ARCH)/bionic
 
 ifeq ($(TARGET_ARCH),arm)
 LOCAL_CFLAGS += -DANDROID_ARM_LINKER
diff --git a/linker/arch/x86/begin.S b/linker/arch/x86/begin.S
index b4427e0..0c0fc3d 100644
--- a/linker/arch/x86/begin.S
+++ b/linker/arch/x86/begin.S
@@ -44,3 +44,4 @@
         popl   %esp
         jmp    *%eax
 
+#include "__stack_chk_fail_local.S"
diff --git a/linker/dlfcn.c b/linker/dlfcn.c
index ac7e5d3..3d0384f 100644
--- a/linker/dlfcn.c
+++ b/linker/dlfcn.c
@@ -60,7 +60,7 @@
     if (unlikely(ret == NULL)) {
         set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY);
     } else {
-        call_constructors_recursive(ret);
+        soinfo_call_constructors(ret);
         ret->refcount++;
     }
     pthread_mutex_unlock(&dl_lock);
@@ -103,7 +103,7 @@
         }
     } else {
         found = (soinfo*)handle;
-        sym = lookup_in_library(found, symbol);
+        sym = soinfo_lookup(found, symbol);
     }
 
     if(likely(sym != 0)) {
@@ -141,7 +141,7 @@
         info->dli_fbase = (void*)si->base;
 
         /* Determine if any symbol in the library contains the specified address */
-        Elf32_Sym *sym = find_containing_symbol(addr, si);
+        Elf32_Sym *sym = soinfo_find_symbol(si, addr);
 
         if(sym != NULL) {
             info->dli_sname = si->strtab + sym->st_name;
@@ -159,7 +159,7 @@
 int dlclose(void *handle)
 {
     pthread_mutex_lock(&dl_lock);
-    (void)unload_library((soinfo*)handle);
+    (void)soinfo_unload((soinfo*)handle);
     pthread_mutex_unlock(&dl_lock);
     return 0;
 }
diff --git a/linker/linker.c b/linker/linker.c
index df4a8b1..0a93130 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -50,6 +50,7 @@
 #include "linker_debug.h"
 #include "linker_environ.h"
 #include "linker_format.h"
+#include "linker_phdr.h"
 
 #define ALLOW_SYMBOLS_FROM_MAIN 1
 #define SO_MAX 128
@@ -82,7 +83,7 @@
 */
 
 
-static int link_image(soinfo *si, unsigned wr_offset);
+static int soinfo_link_image(soinfo *si, unsigned wr_offset);
 
 static int socount = 0;
 static soinfo sopool[SO_MAX];
@@ -125,10 +126,6 @@
 unsigned bitmask[4096];
 #endif
 
-#ifndef PT_ARM_EXIDX
-#define PT_ARM_EXIDX    0x70000001      /* .ARM.exidx segment */
-#endif
-
 #define HOODLUM(name, ret, ...)                                               \
     ret name __VA_ARGS__                                                      \
     {                                                                         \
@@ -254,7 +251,7 @@
     rtld_db_dlactivity();
 }
 
-static soinfo *alloc_info(const char *name)
+static soinfo *soinfo_alloc(const char *name)
 {
     soinfo *si;
 
@@ -263,7 +260,7 @@
         return NULL;
     }
 
-    /* The freelist is populated when we call free_info(), which in turn is
+    /* The freelist is populated when we call soinfo_free(), which in turn is
        done only by dlclose(), which is not likely to be used.
     */
     if (!freelist) {
@@ -290,7 +287,7 @@
     return si;
 }
 
-static void free_info(soinfo *si)
+static void soinfo_free(soinfo *si)
 {
     soinfo *prev = NULL, *trav;
 
@@ -347,7 +344,7 @@
     for (si = solist; si != 0; si = si->next){
         if ((addr >= si->base) && (addr < (si->base + si->size))) {
             *pcount = si->ARM_exidx_count;
-            return (_Unwind_Ptr)(si->base + (unsigned long)si->ARM_exidx);
+            return (_Unwind_Ptr)si->ARM_exidx;
         }
     }
    *pcount = 0;
@@ -377,7 +374,7 @@
 }
 #endif
 
-static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name)
+static Elf32_Sym *soinfo_elf_lookup(soinfo *si, unsigned hash, const char *name)
 {
     Elf32_Sym *s;
     Elf32_Sym *symtab = si->symtab;
@@ -396,8 +393,8 @@
         switch(ELF32_ST_BIND(s->st_info)){
         case STB_GLOBAL:
         case STB_WEAK:
-                /* no section == undefined */
-            if(s->st_shndx == 0) continue;
+            if(s->st_shndx == SHN_UNDEF)
+                continue;
 
             TRACE_TYPE(LOOKUP, "%5d FOUND %s in %s (%08x) %d\n", pid,
                        name, si->name, s->st_value, s->st_size);
@@ -423,7 +420,7 @@
 }
 
 static Elf32_Sym *
-_do_lookup(soinfo *si, const char *name, unsigned *base)
+soinfo_do_lookup(soinfo *si, const char *name, Elf32_Addr *offset)
 {
     unsigned elf_hash = elfhash(name);
     Elf32_Sym *s;
@@ -441,14 +438,14 @@
      * and some the first non-weak definition.   This is system dependent.
      * Here we return the first definition found for simplicity.  */
 
-    s = _elf_lookup(si, elf_hash, name);
+    s = soinfo_elf_lookup(si, elf_hash, name);
     if(s != NULL)
         goto done;
 
     /* Next, look for it in the preloads list */
     for(i = 0; preloads[i] != NULL; i++) {
         lsi = preloads[i];
-        s = _elf_lookup(lsi, elf_hash, name);
+        s = soinfo_elf_lookup(lsi, elf_hash, name);
         if(s != NULL)
             goto done;
     }
@@ -464,8 +461,8 @@
 
             DEBUG("%5d %s: looking up %s in %s\n",
                   pid, si->name, name, lsi->name);
-            s = _elf_lookup(lsi, elf_hash, name);
-            if ((s != NULL) && (s->st_shndx != SHN_UNDEF))
+            s = soinfo_elf_lookup(lsi, elf_hash, name);
+            if (s != NULL)
                 goto done;
         }
     }
@@ -479,16 +476,17 @@
         lsi = somain;
         DEBUG("%5d %s: looking up %s in executable %s\n",
               pid, si->name, name, lsi->name);
-        s = _elf_lookup(lsi, elf_hash, name);
+        s = soinfo_elf_lookup(lsi, elf_hash, name);
     }
 #endif
 
 done:
     if(s != NULL) {
         TRACE_TYPE(LOOKUP, "%5d si %s sym %s s->st_value = 0x%08x, "
-                   "found in %s, base = 0x%08x\n",
-                   pid, si->name, name, s->st_value, lsi->name, lsi->base);
-        *base = lsi->base;
+                   "found in %s, base = 0x%08x, load bias = 0x%08x\n",
+                   pid, si->name, name, s->st_value,
+                   lsi->name, lsi->base, lsi->load_bias);
+        *offset = lsi->load_bias;
         return s;
     }
 
@@ -498,9 +496,9 @@
 /* This is used by dl_sym().  It performs symbol lookup only within the
    specified soinfo object and not in any of its dependencies.
  */
-Elf32_Sym *lookup_in_library(soinfo *si, const char *name)
+Elf32_Sym *soinfo_lookup(soinfo *si, const char *name)
 {
-    return _elf_lookup(si, elfhash(name), name);
+    return soinfo_elf_lookup(si, elfhash(name), name);
 }
 
 /* This is used by dl_sym().  It performs a global symbol lookup.
@@ -519,7 +517,7 @@
     {
         if(si->flags & FLAG_ERROR)
             continue;
-        s = _elf_lookup(si, elf_hash, name);
+        s = soinfo_elf_lookup(si, elf_hash, name);
         if (s != NULL) {
             *found = si;
             break;
@@ -549,7 +547,7 @@
     return NULL;
 }
 
-Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si)
+Elf32_Sym *soinfo_find_symbol(soinfo* si, const void *addr)
 {
     unsigned int i;
     unsigned soaddr = (unsigned)addr - si->base;
@@ -584,7 +582,7 @@
 }
 #endif
 
-static const char *sopaths[] = {
+static const char * const sopaths[] = {
     "/vendor/lib",
     "/system/lib",
     0
@@ -596,7 +594,7 @@
     struct stat filestat;
 
     if ((stat(name, &filestat) >= 0) && S_ISREG(filestat.st_mode)) {
-        if ((fd = open(name, O_RDONLY)) >= 0)
+        if ((fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY))) >= 0)
             return fd;
     }
 
@@ -607,7 +605,7 @@
 {
     int fd;
     char buf[512];
-    const char **path;
+    const char * const*path;
     int n;
 
     TRACE("[ %5d opening %s ]\n", pid, name);
@@ -640,10 +638,6 @@
     return -1;
 }
 
-/* temporary space for holding the first page of the shared lib
- * which contains the elf header (with the pht). */
-static unsigned char __header[PAGE_SIZE];
-
 typedef struct {
     long mmap_addr;
     char tag[4]; /* 'P', 'R', 'E', ' ' */
@@ -654,21 +648,20 @@
 static unsigned long
 is_prelinked(int fd, const char *name)
 {
-    off_t sz;
-    prelink_info_t info;
-
-    sz = lseek(fd, -sizeof(prelink_info_t), SEEK_END);
+    off_t sz = lseek(fd, -sizeof(prelink_info_t), SEEK_END);
     if (sz < 0) {
         DL_ERR("lseek() failed!");
         return 0;
     }
 
-    if (read(fd, &info, sizeof(info)) != sizeof(info)) {
+    prelink_info_t info;
+    int rc = TEMP_FAILURE_RETRY(read(fd, &info, sizeof(info)));
+    if (rc != sizeof(info)) {
         WARN("Could not read prelink_info_t structure for `%s`\n", name);
         return 0;
     }
 
-    if (strncmp(info.tag, "PRE ", 4)) {
+    if (memcmp(info.tag, "PRE ", 4)) {
         WARN("`%s` is not a prelinked library\n", name);
         return 0;
     }
@@ -676,8 +669,8 @@
     return (unsigned long)info.mmap_addr;
 }
 
-/* verify_elf_object
- *      Verifies if the object @ base is a valid ELF object
+/* verify_elf_header
+ *      Verifies the content of an ELF header.
  *
  * Args:
  *
@@ -686,10 +679,8 @@
  *      -1 if no valid ELF object is found @ base.
  */
 static int
-verify_elf_object(void *base, const char *name)
+verify_elf_header(const Elf32_Ehdr* hdr)
 {
-    Elf32_Ehdr *hdr = (Elf32_Ehdr *) base;
-
     if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1;
     if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
     if (hdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
@@ -705,412 +696,76 @@
 }
 
 
-/* get_lib_extents
- *      Retrieves the base (*base) address where the ELF object should be
- *      mapped and its overall memory size (*total_sz).
- *
- * Args:
- *      fd: Opened file descriptor for the library
- *      name: The name of the library
- *      _hdr: Pointer to the header page of the library
- *      total_sz: Total size of the memory that should be allocated for
- *                this library
- *
- * Returns:
- *      -1 if there was an error while trying to get the lib extents.
- *         The possible reasons are:
- *             - Could not determine if the library was prelinked.
- *             - The library provided is not a valid ELF object
- *       0 if the library did not request a specific base offset (normal
- *         for non-prelinked libs)
- *     > 0 if the library requests a specific address to be mapped to.
- *         This indicates a pre-linked library.
- */
-static unsigned
-get_lib_extents(int fd, const char *name, void *__hdr, unsigned *total_sz)
+static soinfo *
+load_library(const char *name)
 {
+    int fd = open_library(name);
+    int ret, cnt;
+    unsigned ext_sz;
     unsigned req_base;
-    unsigned min_vaddr = 0xffffffff;
-    unsigned max_vaddr = 0;
-    unsigned char *_hdr = (unsigned char *)__hdr;
-    Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr;
-    Elf32_Phdr *phdr;
-    int cnt;
+    const char *bname;
+    struct stat sb;
+    soinfo *si = NULL;
+    Elf32_Ehdr  header[1];
+    int         phdr_count;
+    void*       phdr_mmap = NULL;
+    Elf32_Addr  phdr_size;
+    const Elf32_Phdr* phdr_table;
 
-    TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name);
-    if (verify_elf_object(_hdr, name) < 0) {
-        DL_ERR("%5d - %s is not a valid ELF object", pid, name);
-        return (unsigned)-1;
+    void*       load_start = NULL;
+    Elf32_Addr  load_size = 0;
+    Elf32_Addr  load_bias = 0;
+
+    if (fd == -1) {
+        DL_ERR("Library '%s' not found", name);
+        return NULL;
+    }
+
+    /* Read the ELF header first */
+    ret = TEMP_FAILURE_RETRY(read(fd, (void*)header, sizeof(header)));
+    if (ret < 0) {
+        DL_ERR("%5d can't read file %s: %s", pid, name, strerror(errno));
+        goto fail;
+    }
+    if (ret != (int)sizeof(header)) {
+        DL_ERR("%5d too small to be an ELF executable: %s", pid, name);
+        goto fail;
+    }
+    if (verify_elf_header(header) < 0) {
+        DL_ERR("%5d not a valid ELF executable: %s", pid, name);
+        goto fail;
+    }
+
+    /* Then read the program header table */
+    ret = phdr_table_load(fd, header->e_phoff, header->e_phnum,
+                          &phdr_mmap, &phdr_size, &phdr_table);
+    if (ret < 0) {
+        DL_ERR("%5d can't load program header table: %s: %s", pid,
+               name, strerror(errno));
+        goto fail;
+    }
+    phdr_count = header->e_phnum;
+
+    /* Get the load extents and the prelinked load address, if any */
+    ext_sz = phdr_table_get_load_size(phdr_table, phdr_count);
+    if (ext_sz == 0) {
+        DL_ERR("%5d no loadable segments in file: %s", pid, name);
+        goto fail;
     }
 
     req_base = (unsigned) is_prelinked(fd, name);
-    if (req_base == (unsigned)-1)
-        return -1;
-    else if (req_base != 0) {
+    if (req_base == (unsigned)-1) {
+        DL_ERR("%5d can't read end of library: %s: %s", pid, name,
+               strerror(errno));
+        goto fail;
+    }
+    if (req_base != 0) {
         TRACE("[ %5d - Prelinked library '%s' requesting base @ 0x%08x ]\n",
               pid, name, req_base);
     } else {
         TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name);
     }
 
-    phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff);
-
-    /* find the min/max p_vaddrs from all the PT_LOAD segments so we can
-     * get the range. */
-    for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) {
-        if (phdr->p_type == PT_LOAD) {
-            if ((phdr->p_vaddr + phdr->p_memsz) > max_vaddr)
-                max_vaddr = phdr->p_vaddr + phdr->p_memsz;
-            if (phdr->p_vaddr < min_vaddr)
-                min_vaddr = phdr->p_vaddr;
-        }
-    }
-
-    if ((min_vaddr == 0xffffffff) && (max_vaddr == 0)) {
-        DL_ERR("%5d - No loadable segments found in %s.", pid, name);
-        return (unsigned)-1;
-    }
-
-    /* truncate min_vaddr down to page boundary */
-    min_vaddr &= ~PAGE_MASK;
-
-    /* round max_vaddr up to the next page */
-    max_vaddr = (max_vaddr + PAGE_SIZE - 1) & ~PAGE_MASK;
-
-    *total_sz = (max_vaddr - min_vaddr);
-    return (unsigned)req_base;
-}
-
-/* reserve_mem_region
- *
- *     This function reserves a chunk of memory to be used for mapping in
- *     a prelinked shared library. We reserve the entire memory region here, and
- *     then the rest of the linker will relocate the individual loadable
- *     segments into the correct locations within this memory range.
- *
- * Args:
- *     si->base: The requested base of the allocation.
- *     si->size: The size of the allocation.
- *
- * Returns:
- *     -1 on failure, and 0 on success.  On success, si->base will contain
- *     the virtual address at which the library will be mapped.
- */
-
-static int reserve_mem_region(soinfo *si)
-{
-    void *base = mmap((void *)si->base, si->size, PROT_NONE,
-                      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-    if (base == MAP_FAILED) {
-        DL_ERR("%5d can NOT map (%sprelinked) library '%s' at 0x%08x "
-              "as requested, will try general pool: %d (%s)",
-              pid, (si->base ? "" : "non-"), si->name, si->base,
-              errno, strerror(errno));
-        return -1;
-    } else if (base != (void *)si->base) {
-        DL_ERR("OOPS: %5d %sprelinked library '%s' mapped at 0x%08x, "
-              "not at 0x%08x", pid, (si->base ? "" : "non-"),
-              si->name, (unsigned)base, si->base);
-        munmap(base, si->size);
-        return -1;
-    }
-    return 0;
-}
-
-static int alloc_mem_region(soinfo *si)
-{
-    if (si->base) {
-        /* Attempt to mmap a prelinked library. */
-        return reserve_mem_region(si);
-    }
-
-    /* This is not a prelinked library, so we use the kernel's default
-       allocator.
-    */
-
-    void *base = mmap(NULL, si->size, PROT_NONE,
-                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-    if (base == MAP_FAILED) {
-        DL_ERR("%5d mmap of library '%s' failed: %d (%s)\n",
-              pid, si->name,
-              errno, strerror(errno));
-        goto err;
-    }
-    si->base = (unsigned) base;
-    PRINT("%5d mapped library '%s' to %08x via kernel allocator.\n",
-          pid, si->name, si->base);
-    return 0;
-
-err:
-    DL_ERR("OOPS: %5d cannot map library '%s'. no vspace available.",
-          pid, si->name);
-    return -1;
-}
-
-#define MAYBE_MAP_FLAG(x,from,to)    (((x) & (from)) ? (to) : 0)
-#define PFLAGS_TO_PROT(x)            (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \
-                                      MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
-                                      MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
-/* load_segments
- *
- *     This function loads all the loadable (PT_LOAD) segments into memory
- *     at their appropriate memory offsets off the base address.
- *
- * Args:
- *     fd: Open file descriptor to the library to load.
- *     header: Pointer to a header page that contains the ELF header.
- *             This is needed since we haven't mapped in the real file yet.
- *     si: ptr to soinfo struct describing the shared object.
- *
- * Returns:
- *     0 on success, -1 on failure.
- */
-static int
-load_segments(int fd, void *header, soinfo *si)
-{
-    Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header;
-    Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff);
-    Elf32_Addr base = (Elf32_Addr) si->base;
-    int cnt;
-    unsigned len;
-    Elf32_Addr tmp;
-    unsigned char *pbase;
-    unsigned char *extra_base;
-    unsigned extra_len;
-    unsigned total_sz = 0;
-
-    si->wrprotect_start = 0xffffffff;
-    si->wrprotect_end = 0;
-
-    TRACE("[ %5d - Begin loading segments for '%s' @ 0x%08x ]\n",
-          pid, si->name, (unsigned)si->base);
-    /* Now go through all the PT_LOAD segments and map them into memory
-     * at the appropriate locations. */
-    for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) {
-        if (phdr->p_type == PT_LOAD) {
-            DEBUG_DUMP_PHDR(phdr, "PT_LOAD", pid);
-            /* we want to map in the segment on a page boundary */
-            tmp = base + (phdr->p_vaddr & (~PAGE_MASK));
-            /* add the # of bytes we masked off above to the total length. */
-            len = phdr->p_filesz + (phdr->p_vaddr & PAGE_MASK);
-
-            TRACE("[ %d - Trying to load segment from '%s' @ 0x%08x "
-                  "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x ]\n", pid, si->name,
-                  (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset);
-            pbase = mmap((void *)tmp, len, PFLAGS_TO_PROT(phdr->p_flags),
-                         MAP_PRIVATE | MAP_FIXED, fd,
-                         phdr->p_offset & (~PAGE_MASK));
-            if (pbase == MAP_FAILED) {
-                DL_ERR("%d failed to map segment from '%s' @ 0x%08x (0x%08x). "
-                      "p_vaddr=0x%08x p_offset=0x%08x", pid, si->name,
-                      (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset);
-                goto fail;
-            }
-
-            /* If 'len' didn't end on page boundary, and it's a writable
-             * segment, zero-fill the rest. */
-            if ((len & PAGE_MASK) && (phdr->p_flags & PF_W))
-                memset((void *)(pbase + len), 0, PAGE_SIZE - (len & PAGE_MASK));
-
-            /* Check to see if we need to extend the map for this segment to
-             * cover the diff between filesz and memsz (i.e. for bss).
-             *
-             *  base           _+---------------------+  page boundary
-             *                  .                     .
-             *                  |                     |
-             *                  .                     .
-             *  pbase          _+---------------------+  page boundary
-             *                  |                     |
-             *                  .                     .
-             *  base + p_vaddr _|                     |
-             *                  . \          \        .
-             *                  . | filesz   |        .
-             *  pbase + len    _| /          |        |
-             *     <0 pad>      .            .        .
-             *  extra_base     _+------------|--------+  page boundary
-             *               /  .            .        .
-             *               |  .            .        .
-             *               |  +------------|--------+  page boundary
-             *  extra_len->  |  |            |        |
-             *               |  .            | memsz  .
-             *               |  .            |        .
-             *               \ _|            /        |
-             *                  .                     .
-             *                  |                     |
-             *                 _+---------------------+  page boundary
-             */
-            tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) &
-                                    (~PAGE_MASK));
-            if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) {
-                extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp;
-                TRACE("[ %5d - Need to extend segment from '%s' @ 0x%08x "
-                      "(0x%08x) ]\n", pid, si->name, (unsigned)tmp, extra_len);
-                /* map in the extra page(s) as anonymous into the range.
-                 * This is probably not necessary as we already mapped in
-                 * the entire region previously, but we just want to be
-                 * sure. This will also set the right flags on the region
-                 * (though we can probably accomplish the same thing with
-                 * mprotect).
-                 */
-                extra_base = mmap((void *)tmp, extra_len,
-                                  PFLAGS_TO_PROT(phdr->p_flags),
-                                  MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
-                                  -1, 0);
-                if (extra_base == MAP_FAILED) {
-                    DL_ERR("[ %5d - failed to extend segment from '%s' @ 0x%08x"
-                           " (0x%08x) ]", pid, si->name, (unsigned)tmp,
-                          extra_len);
-                    goto fail;
-                }
-                /* TODO: Check if we need to memset-0 this region.
-                 * Anonymous mappings are zero-filled copy-on-writes, so we
-                 * shouldn't need to. */
-                TRACE("[ %5d - Segment from '%s' extended @ 0x%08x "
-                      "(0x%08x)\n", pid, si->name, (unsigned)extra_base,
-                      extra_len);
-            }
-            /* set the len here to show the full extent of the segment we
-             * just loaded, mostly for debugging */
-            len = (((unsigned)base + phdr->p_vaddr + phdr->p_memsz +
-                    PAGE_SIZE - 1) & (~PAGE_MASK)) - (unsigned)pbase;
-            TRACE("[ %5d - Successfully loaded segment from '%s' @ 0x%08x "
-                  "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x\n", pid, si->name,
-                  (unsigned)pbase, len, phdr->p_vaddr, phdr->p_offset);
-            total_sz += len;
-            /* Make the section writable just in case we'll have to write to
-             * it during relocation (i.e. text segment). However, we will
-             * remember what range of addresses should be write protected.
-             *
-             */
-            if (!(phdr->p_flags & PF_W)) {
-                if ((unsigned)pbase < si->wrprotect_start)
-                    si->wrprotect_start = (unsigned)pbase;
-                if (((unsigned)pbase + len) > si->wrprotect_end)
-                    si->wrprotect_end = (unsigned)pbase + len;
-                mprotect(pbase, len,
-                         PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE);
-            }
-        } else if (phdr->p_type == PT_DYNAMIC) {
-            DEBUG_DUMP_PHDR(phdr, "PT_DYNAMIC", pid);
-            /* this segment contains the dynamic linking information */
-            si->dynamic = (unsigned *)(base + phdr->p_vaddr);
-        } else if (phdr->p_type == PT_GNU_RELRO) {
-            if ((phdr->p_vaddr >= si->size)
-                    || ((phdr->p_vaddr + phdr->p_memsz) > si->size)
-                    || ((base + phdr->p_vaddr + phdr->p_memsz) < base)) {
-                DL_ERR("%d invalid GNU_RELRO in '%s' "
-                       "p_vaddr=0x%08x p_memsz=0x%08x", pid, si->name,
-                       phdr->p_vaddr, phdr->p_memsz);
-                goto fail;
-            }
-            si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr);
-            si->gnu_relro_len = (unsigned) phdr->p_memsz;
-        } else {
-#ifdef ANDROID_ARM_LINKER
-            if (phdr->p_type == PT_ARM_EXIDX) {
-                DEBUG_DUMP_PHDR(phdr, "PT_ARM_EXIDX", pid);
-                /* exidx entries (used for stack unwinding) are 8 bytes each.
-                 */
-                si->ARM_exidx = (unsigned *)phdr->p_vaddr;
-                si->ARM_exidx_count = phdr->p_memsz / 8;
-            }
-#endif
-        }
-
-    }
-
-    /* Sanity check */
-    if (total_sz > si->size) {
-        DL_ERR("%5d - Total length (0x%08x) of mapped segments from '%s' is "
-              "greater than what was allocated (0x%08x). THIS IS BAD!",
-              pid, total_sz, si->name, si->size);
-        goto fail;
-    }
-
-    TRACE("[ %5d - Finish loading segments for '%s' @ 0x%08x. "
-          "Total memory footprint: 0x%08x bytes ]\n", pid, si->name,
-          (unsigned)si->base, si->size);
-    return 0;
-
-fail:
-    /* We can just blindly unmap the entire region even though some things
-     * were mapped in originally with anonymous and others could have been
-     * been mapped in from the file before we failed. The kernel will unmap
-     * all the pages in the range, irrespective of how they got there.
-     */
-    munmap((void *)si->base, si->size);
-    si->flags |= FLAG_ERROR;
-    return -1;
-}
-
-/* TODO: Implement this to take care of the fact that Android ARM
- * ELF objects shove everything into a single loadable segment that has the
- * write bit set. wr_offset is then used to set non-(data|bss) pages to be
- * non-writable.
- */
-#if 0
-static unsigned
-get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr)
-{
-    Elf32_Shdr *shdr_start;
-    Elf32_Shdr *shdr;
-    int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr);
-    int cnt;
-    unsigned wr_offset = 0xffffffff;
-
-    shdr_start = mmap(0, shdr_sz, PROT_READ, MAP_PRIVATE, fd,
-                      ehdr->e_shoff & (~PAGE_MASK));
-    if (shdr_start == MAP_FAILED) {
-        WARN("%5d - Could not read section header info from '%s'. Will not "
-             "not be able to determine write-protect offset.\n", pid, name);
-        return (unsigned)-1;
-    }
-
-    for(cnt = 0, shdr = shdr_start; cnt < ehdr->e_shnum; ++cnt, ++shdr) {
-        if ((shdr->sh_type != SHT_NULL) && (shdr->sh_flags & SHF_WRITE) &&
-            (shdr->sh_addr < wr_offset)) {
-            wr_offset = shdr->sh_addr;
-        }
-    }
-
-    munmap(shdr_start, shdr_sz);
-    return wr_offset;
-}
-#endif
-
-static soinfo *
-load_library(const char *name)
-{
-    int fd = open_library(name);
-    int cnt;
-    unsigned ext_sz;
-    unsigned req_base;
-    const char *bname;
-    soinfo *si = NULL;
-    Elf32_Ehdr *hdr;
-
-    if(fd == -1) {
-        DL_ERR("Library '%s' not found", name);
-        return NULL;
-    }
-
-    /* We have to read the ELF header to figure out what to do with this image
-     */
-    if (lseek(fd, 0, SEEK_SET) < 0) {
-        DL_ERR("lseek() failed!");
-        goto fail;
-    }
-
-    if ((cnt = read(fd, &__header[0], PAGE_SIZE)) < 0) {
-        DL_ERR("read() failed!");
-        goto fail;
-    }
-
-    /* Parse the ELF header and get the size of the memory footprint for
-     * the library */
-    req_base = get_lib_extents(fd, name, &__header[0], &ext_sz);
-    if (req_base == (unsigned)-1)
-        goto fail;
     TRACE("[ %5d - '%s' (%s) wants base=0x%08x sz=0x%08x ]\n", pid, name,
           (req_base ? "prelinked" : "not pre-linked"), req_base, ext_sz);
 
@@ -1120,40 +775,76 @@
      * soinfo struct here is a lot more convenient.
      */
     bname = strrchr(name, '/');
-    si = alloc_info(bname ? bname + 1 : name);
+    si = soinfo_alloc(bname ? bname + 1 : name);
     if (si == NULL)
         goto fail;
 
-    /* Carve out a chunk of memory where we will map in the individual
-     * segments */
-    si->base = req_base;
-    si->size = ext_sz;
-    si->flags = 0;
-    si->entry = 0;
-    si->dynamic = (unsigned *)-1;
-    if (alloc_mem_region(si) < 0)
-        goto fail;
-
-    TRACE("[ %5d allocated memory for %s @ %p (0x%08x) ]\n",
-          pid, name, (void *)si->base, (unsigned) ext_sz);
-
-    /* Now actually load the library's segments into right places in memory */
-    if (load_segments(fd, &__header[0], si) < 0) {
+    /* Reserve address space for all loadable segments */
+    ret = phdr_table_reserve_memory(phdr_table,
+                                    phdr_count,
+                                    req_base,
+                                    &load_start,
+                                    &load_size,
+                                    &load_bias);
+    if (ret < 0) {
+        DL_ERR("%5d Can't reserve %d bytes from 0x%08x in address space for %s: %s",
+               pid, ext_sz, req_base, name, strerror(errno));
         goto fail;
     }
 
-    /* this might not be right. Technically, we don't even need this info
-     * once we go through 'load_segments'. */
-    hdr = (Elf32_Ehdr *)si->base;
-    si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff);
-    si->phnum = hdr->e_phnum;
-    /**/
+    TRACE("[ %5d allocated memory for %s @ %p (0x%08x) ]\n",
+          pid, name, load_start, load_size);
 
+    /* Map all the segments in our address space with default protections */
+    ret = phdr_table_load_segments(phdr_table,
+                                   phdr_count,
+                                   load_start,
+                                   load_size,
+                                   load_bias,
+                                   fd);
+    if (ret < 0) {
+        DL_ERR("%5d Can't map loadable segments for %s: %s",
+               pid, name, strerror(errno));
+        goto fail;
+    }
+
+    /* Unprotect the segments, i.e. make them writable, to allow
+     * relocations to work properly. We will later call
+     * phdr_table_protect_segments() after all of them are applied
+     * and all constructors are run.
+     */
+    ret = phdr_table_unprotect_segments(phdr_table,
+                                        phdr_count,
+                                        load_bias);
+    if (ret < 0) {
+        DL_ERR("%5d Can't unprotect loadable segments for %s: %s",
+               pid, name, strerror(errno));
+        goto fail;
+    }
+
+    si->base = (Elf32_Addr) load_start;
+    si->size = load_size;
+    si->load_bias = load_bias;
+    si->flags = 0;
+    si->entry = 0;
+    si->dynamic = (unsigned *)-1;
+    si->phnum = phdr_count;
+    si->phdr = phdr_table_get_loaded_phdr(phdr_table, phdr_count, load_bias);
+    if (si->phdr == NULL) {
+        DL_ERR("%5d Can't find loaded PHDR for %s",
+               pid, name);
+        goto fail;
+    }
+
+    phdr_table_unload(phdr_mmap, phdr_size);
     close(fd);
     return si;
 
 fail:
-    if (si) free_info(si);
+    if (si) soinfo_free(si);
+    if (phdr_mmap != NULL) {
+        phdr_table_unload(phdr_mmap, phdr_size);
+    }
     close(fd);
     return NULL;
 }
@@ -1168,7 +859,7 @@
     TRACE("[ %5d init_library base=0x%08x sz=0x%08x name='%s') ]\n",
           pid, si->base, si->size, si->name);
 
-    if(link_image(si, wr_offset)) {
+    if(soinfo_link_image(si, wr_offset)) {
             /* We failed to link.  However, we can only restore libbase
             ** if no additional libraries have moved it since we updated it.
             */
@@ -1219,7 +910,7 @@
  *   for non-prelinked libraries, find a way to decrement libbase
  */
 static void call_destructors(soinfo *si);
-unsigned unload_library(soinfo *si)
+unsigned soinfo_unload(soinfo *si)
 {
     unsigned *d;
     if (si->refcount == 1) {
@@ -1228,16 +919,13 @@
 
         /*
          * Make sure that we undo the PT_GNU_RELRO protections we added
-         * in link_image. This is needed to undo the DT_NEEDED hack below.
+         * in soinfo_link_image. This is needed to undo the DT_NEEDED hack below.
          */
-        if ((si->gnu_relro_start != 0) && (si->gnu_relro_len != 0)) {
-            Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK);
-            unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len;
-            if (mprotect((void *) start, len, PROT_READ | PROT_WRITE) < 0)
-                DL_ERR("%5d %s: could not undo GNU_RELRO protections. "
-                       "Expect a crash soon. errno=%d (%s)",
-                       pid, si->name, errno, strerror(errno));
-
+        if (phdr_table_unprotect_gnu_relro(si->phdr, si->phnum,
+                                           si->load_bias) < 0) {
+            DL_ERR("%5d %s: could not undo GNU_RELRO protections. "
+                    "Expect a crash soon. errno=%d (%s)",
+                    pid, si->name, errno, strerror(errno));
         }
 
         for(d = si->dynamic; *d; d += 2) {
@@ -1246,13 +934,13 @@
 
                 // The next line will segfault if the we don't undo the
                 // PT_GNU_RELRO protections (see comments above and in
-                // link_image().
+                // soinfo_link_image().
                 d[1] = 0;
 
                 if (validate_soinfo(lsi)) {
                     TRACE("%5d %s needs to unload %s\n", pid,
                           si->name, lsi->name);
-                    unload_library(lsi);
+                    soinfo_unload(lsi);
                 }
                 else
                     DL_ERR("%5d %s: could not unload dependent library",
@@ -1262,7 +950,7 @@
 
         munmap((char *)si->base, si->size);
         notify_gdb_of_unload(si);
-        free_info(si);
+        soinfo_free(si);
         si->refcount = 0;
     }
     else {
@@ -1277,19 +965,20 @@
  * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned
  * long.
  */
-static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count)
+static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
 {
     Elf32_Sym *symtab = si->symtab;
     const char *strtab = si->strtab;
     Elf32_Sym *s;
     unsigned base;
+    Elf32_Addr offset;
     Elf32_Rel *start = rel;
     unsigned idx;
 
     for (idx = 0; idx < count; ++idx) {
         unsigned type = ELF32_R_TYPE(rel->r_info);
         unsigned sym = ELF32_R_SYM(rel->r_info);
-        unsigned reloc = (unsigned)(rel->r_offset + si->base);
+        unsigned reloc = (unsigned)(rel->r_offset + si->load_bias);
         unsigned sym_addr = 0;
         char *sym_name = NULL;
 
@@ -1297,7 +986,7 @@
               si->name, idx);
         if(sym != 0) {
             sym_name = (char *)(strtab + symtab[sym].st_name);
-            s = _do_lookup(si, sym_name, &base);
+            s = soinfo_do_lookup(si, sym_name, &offset);
             if(s == NULL) {
                 /* We only allow an undefined symbol if this is a weak
                    reference..   */
@@ -1364,7 +1053,7 @@
                 return -1;
             }
 #endif
-                sym_addr = (unsigned)(s->st_value + base);
+                sym_addr = (unsigned)(s->st_value + offset);
 	    }
             COUNT_RELOC(RELOC_SYMBOL);
         } else {
@@ -1516,7 +1205,7 @@
     }
 }
 
-void call_constructors_recursive(soinfo *si)
+void soinfo_call_constructors(soinfo *si)
 {
     if (si->constructors_called)
         return;
@@ -1527,9 +1216,9 @@
     // libc_malloc_debug_leak.so:
     // 1. The program depends on libc, so libc's constructor is called here.
     // 2. The libc constructor calls dlopen() to load libc_malloc_debug_leak.so.
-    // 3. dlopen() calls call_constructors_recursive() with the newly created
+    // 3. dlopen() calls soinfo_call_constructors() with the newly created
     //    soinfo for libc_malloc_debug_leak.so.
-    // 4. The debug so depends on libc, so call_constructors_recursive() is
+    // 4. The debug so depends on libc, so soinfo_call_constructors() is
     //    called again with the libc soinfo. If it doesn't trigger the early-
     //    out above, the libc constructor will be called again (recursively!).
     si->constructors_called = 1;
@@ -1557,7 +1246,7 @@
                     DL_ERR("%5d bad DT_NEEDED pointer in %s",
                            pid, si->name);
                 } else {
-                    call_constructors_recursive(lsi);
+                    soinfo_call_constructors(lsi);
                 }
             }
         }
@@ -1603,7 +1292,7 @@
     int dev_null, i, status;
     int return_value = 0;
 
-    dev_null = open("/dev/null", O_RDWR);
+    dev_null = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
     if (dev_null < 0) {
         DL_ERR("Cannot open /dev/null.");
         return -1;
@@ -1666,120 +1355,69 @@
     return return_value;
 }
 
-static int link_image(soinfo *si, unsigned wr_offset)
+static int soinfo_link_image(soinfo *si, unsigned wr_offset)
 {
     unsigned *d;
-    Elf32_Phdr *phdr = si->phdr;
+    /* "base" might wrap around UINT32_MAX. */
+    Elf32_Addr base = si->load_bias;
+    const Elf32_Phdr *phdr = si->phdr;
     int phnum = si->phnum;
+    int relocating_linker = (si->flags & FLAG_LINKER) != 0;
 
-    INFO("[ %5d linking %s ]\n", pid, si->name);
-    DEBUG("%5d si->base = 0x%08x si->flags = 0x%08x\n", pid,
-          si->base, si->flags);
+    /* We can't debug anything until the linker is relocated */
+    if (!relocating_linker) {
+        INFO("[ %5d linking %s ]\n", pid, si->name);
+        DEBUG("%5d si->base = 0x%08x si->flags = 0x%08x\n", pid,
+            si->base, si->flags);
+    }
 
-    if (si->flags & (FLAG_EXE | FLAG_LINKER)) {
-        /* Locate the needed program segments (DYNAMIC/ARM_EXIDX) for
-         * linkage info if this is the executable or the linker itself. 
-         * If this was a dynamic lib, that would have been done at load time.
-         *
-         * TODO: It's unfortunate that small pieces of this are
-         * repeated from the load_library routine. Refactor this just
-         * slightly to reuse these bits.
-         */
-        si->size = 0;
-        for(; phnum > 0; --phnum, ++phdr) {
-#ifdef ANDROID_ARM_LINKER
-            if(phdr->p_type == PT_ARM_EXIDX) {
-                /* exidx entries (used for stack unwinding) are 8 bytes each.
-                 */
-                si->ARM_exidx = (unsigned *)phdr->p_vaddr;
-                si->ARM_exidx_count = phdr->p_memsz / 8;
-            }
-#endif
-            if (phdr->p_type == PT_LOAD) {
-                /* For the executable, we use the si->size field only in
-                   dl_unwind_find_exidx(), so the meaning of si->size
-                   is not the size of the executable; it is the distance
-                   between the load location of the executable and the last
-                   address of the loadable part of the executable.
-                   We use the range [si->base, si->base + si->size) to
-                   determine whether a PC value falls within the executable
-                   section. Of course, if a value is between si->base and
-                   (si->base + phdr->p_vaddr), it's not in the executable
-                   section, but a) we shouldn't be asking for such a value
-                   anyway, and b) if we have to provide an EXIDX for such a
-                   value, then the executable's EXIDX is probably the better
-                   choice.
-                */
-                DEBUG_DUMP_PHDR(phdr, "PT_LOAD", pid);
-                if (phdr->p_vaddr + phdr->p_memsz > si->size)
-                    si->size = phdr->p_vaddr + phdr->p_memsz;
-                /* try to remember what range of addresses should be write
-                 * protected */
-                if (!(phdr->p_flags & PF_W)) {
-                    unsigned _end;
-
-                    if (si->base + phdr->p_vaddr < si->wrprotect_start)
-                        si->wrprotect_start = si->base + phdr->p_vaddr;
-                    _end = (((si->base + phdr->p_vaddr + phdr->p_memsz + PAGE_SIZE - 1) &
-                             (~PAGE_MASK)));
-                    if (_end > si->wrprotect_end)
-                        si->wrprotect_end = _end;
-                    /* Make the section writable just in case we'll have to
-                     * write to it during relocation (i.e. text segment).
-                     * However, we will remember what range of addresses
-                     * should be write protected.
-                     */
-                    mprotect((void *) (si->base + phdr->p_vaddr),
-                             phdr->p_memsz,
-                             PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE);
-                }
-            } else if (phdr->p_type == PT_DYNAMIC) {
-                if (si->dynamic != (unsigned *)-1) {
-                    DL_ERR("%5d multiple PT_DYNAMIC segments found in '%s'. "
-                          "Segment at 0x%08x, previously one found at 0x%08x",
-                          pid, si->name, si->base + phdr->p_vaddr,
-                          (unsigned)si->dynamic);
-                    goto fail;
-                }
-                DEBUG_DUMP_PHDR(phdr, "PT_DYNAMIC", pid);
-                si->dynamic = (unsigned *) (si->base + phdr->p_vaddr);
-            } else if (phdr->p_type == PT_GNU_RELRO) {
-                if ((phdr->p_vaddr >= si->size)
-                        || ((phdr->p_vaddr + phdr->p_memsz) > si->size)
-                        || ((si->base + phdr->p_vaddr + phdr->p_memsz) < si->base)) {
-                    DL_ERR("%d invalid GNU_RELRO in '%s' "
-                           "p_vaddr=0x%08x p_memsz=0x%08x", pid, si->name,
-                           phdr->p_vaddr, phdr->p_memsz);
-                    goto fail;
-                }
-                si->gnu_relro_start = (Elf32_Addr) (si->base + phdr->p_vaddr);
-                si->gnu_relro_len = (unsigned) phdr->p_memsz;
-            }
+    /* Extract dynamic section */
+    si->dynamic = phdr_table_get_dynamic_section(phdr, phnum, base);
+    if (si->dynamic == NULL) {
+        if (!relocating_linker) {
+            DL_ERR("%5d missing PT_DYNAMIC?!", pid);
+        }
+        goto fail;
+    } else {
+        if (!relocating_linker) {
+            DEBUG("%5d dynamic = %p\n", pid, si->dynamic);
         }
     }
 
-    if (si->dynamic == (unsigned *)-1) {
-        DL_ERR("%5d missing PT_DYNAMIC?!", pid);
-        goto fail;
-    }
+#ifdef ANDROID_ARM_LINKER
+    (void) phdr_table_get_arm_exidx(phdr, phnum, base,
+                                    &si->ARM_exidx, &si->ARM_exidx_count);
+#endif
 
-    DEBUG("%5d dynamic = %p\n", pid, si->dynamic);
+    if (si->flags & (FLAG_EXE | FLAG_LINKER)) {
+        if (phdr_table_unprotect_segments(si->phdr,
+                                          si->phnum,
+                                          si->load_bias) < 0) {
+            /* We can't call DL_ERR if the linker's relocations haven't
+             * been performed yet */
+            if (!relocating_linker) {
+                DL_ERR("%5d Can't unprotect segments for %s: %s",
+                       pid, si->name, strerror(errno));
+            }
+            goto fail;
+        }
+    }
 
     /* extract useful information from dynamic section */
     for(d = si->dynamic; *d; d++){
         DEBUG("%5d d = %p, d[0] = 0x%08x d[1] = 0x%08x\n", pid, d, d[0], d[1]);
         switch(*d++){
         case DT_HASH:
-            si->nbucket = ((unsigned *) (si->base + *d))[0];
-            si->nchain = ((unsigned *) (si->base + *d))[1];
-            si->bucket = (unsigned *) (si->base + *d + 8);
-            si->chain = (unsigned *) (si->base + *d + 8 + si->nbucket * 4);
+            si->nbucket = ((unsigned *) (base + *d))[0];
+            si->nchain = ((unsigned *) (base + *d))[1];
+            si->bucket = (unsigned *) (base + *d + 8);
+            si->chain = (unsigned *) (base + *d + 8 + si->nbucket * 4);
             break;
         case DT_STRTAB:
-            si->strtab = (const char *) (si->base + *d);
+            si->strtab = (const char *) (base + *d);
             break;
         case DT_SYMTAB:
-            si->symtab = (Elf32_Sym *) (si->base + *d);
+            si->symtab = (Elf32_Sym *) (base + *d);
             break;
         case DT_PLTREL:
             if(*d != DT_REL) {
@@ -1788,20 +1426,20 @@
             }
             break;
         case DT_JMPREL:
-            si->plt_rel = (Elf32_Rel*) (si->base + *d);
+            si->plt_rel = (Elf32_Rel*) (base + *d);
             break;
         case DT_PLTRELSZ:
             si->plt_rel_count = *d / 8;
             break;
         case DT_REL:
-            si->rel = (Elf32_Rel*) (si->base + *d);
+            si->rel = (Elf32_Rel*) (base + *d);
             break;
         case DT_RELSZ:
             si->rel_count = *d / 8;
             break;
         case DT_PLTGOT:
             /* Save this in case we decide to do lazy binding. We don't yet. */
-            si->plt_got = (unsigned *)(si->base + *d);
+            si->plt_got = (unsigned *)(base + *d);
             break;
         case DT_DEBUG:
             // Set the DT_DEBUG entry to the addres of _r_debug for GDB
@@ -1811,17 +1449,17 @@
             DL_ERR("%5d DT_RELA not supported", pid);
             goto fail;
         case DT_INIT:
-            si->init_func = (void (*)(void))(si->base + *d);
+            si->init_func = (void (*)(void))(base + *d);
             DEBUG("%5d %s constructors (init func) found at %p\n",
                   pid, si->name, si->init_func);
             break;
         case DT_FINI:
-            si->fini_func = (void (*)(void))(si->base + *d);
+            si->fini_func = (void (*)(void))(base + *d);
             DEBUG("%5d %s destructors (fini func) found at %p\n",
                   pid, si->name, si->fini_func);
             break;
         case DT_INIT_ARRAY:
-            si->init_array = (unsigned *)(si->base + *d);
+            si->init_array = (unsigned *)(base + *d);
             DEBUG("%5d %s constructors (init_array) found at %p\n",
                   pid, si->name, si->init_array);
             break;
@@ -1829,7 +1467,7 @@
             si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr);
             break;
         case DT_FINI_ARRAY:
-            si->fini_array = (unsigned *)(si->base + *d);
+            si->fini_array = (unsigned *)(base + *d);
             DEBUG("%5d %s destructors (fini_array) found at %p\n",
                   pid, si->name, si->fini_array);
             break;
@@ -1837,7 +1475,7 @@
             si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr);
             break;
         case DT_PREINIT_ARRAY:
-            si->preinit_array = (unsigned *)(si->base + *d);
+            si->preinit_array = (unsigned *)(base + *d);
             DEBUG("%5d %s constructors (preinit_array) found at %p\n",
                   pid, si->name, si->preinit_array);
             break;
@@ -1905,52 +1543,31 @@
 
     if(si->plt_rel) {
         DEBUG("[ %5d relocating %s plt ]\n", pid, si->name );
-        if(reloc_library(si, si->plt_rel, si->plt_rel_count))
+        if(soinfo_relocate(si, si->plt_rel, si->plt_rel_count))
             goto fail;
     }
     if(si->rel) {
         DEBUG("[ %5d relocating %s ]\n", pid, si->name );
-        if(reloc_library(si, si->rel, si->rel_count))
+        if(soinfo_relocate(si, si->rel, si->rel_count))
             goto fail;
     }
 
     si->flags |= FLAG_LINKED;
     DEBUG("[ %5d finished linking %s ]\n", pid, si->name);
 
-#if 0
-    /* This is the way that the old dynamic linker did protection of
-     * non-writable areas. It would scan section headers and find where
-     * .text ended (rather where .data/.bss began) and assume that this is
-     * the upper range of the non-writable area. This is too coarse,
-     * and is kept here for reference until we fully move away from single
-     * segment elf objects. See the code in get_wr_offset (also #if'd 0)
-     * that made this possible.
-     */
-    if(wr_offset < 0xffffffff){
-        mprotect((void*) si->base, wr_offset, PROT_READ | PROT_EXEC);
+    /* All relocations are done, we can protect our segments back to
+     * read-only. */
+    if (phdr_table_protect_segments(si->phdr, si->phnum, si->load_bias) < 0) {
+        DL_ERR("%5d Can't protect segments for %s: %s",
+               pid, si->name, strerror(errno));
+        goto fail;
     }
-#else
-    /* TODO: Verify that this does the right thing in all cases, as it
-     * presently probably does not. It is possible that an ELF image will
-     * come with multiple read-only segments. What we ought to do is scan
-     * the program headers again and mprotect all the read-only segments.
-     * To prevent re-scanning the program header, we would have to build a
-     * list of loadable segments in si, and then scan that instead. */
-    if (si->wrprotect_start != 0xffffffff && si->wrprotect_end != 0) {
-        mprotect((void *)si->wrprotect_start,
-                 si->wrprotect_end - si->wrprotect_start,
-                 PROT_READ | PROT_EXEC);
-    }
-#endif
 
-    if (si->gnu_relro_start != 0 && si->gnu_relro_len != 0) {
-        Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK);
-        unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len;
-        if (mprotect((void *) start, len, PROT_READ) < 0) {
-            DL_ERR("%5d GNU_RELRO mprotect of library '%s' failed: %d (%s)\n",
-                   pid, si->name, errno, strerror(errno));
-            goto fail;
-        }
+    /* We can also turn on GNU RELRO protection */
+    if (phdr_table_protect_gnu_relro(si->phdr, si->phnum, si->load_bias) < 0) {
+        DL_ERR("%5d Can't enable GNU RELRO protection for %s: %s",
+               pid, si->name, strerror(errno));
+        goto fail;
     }
 
     /* If this is a SET?ID program, dup /dev/null to opened stdin,
@@ -2022,7 +1639,7 @@
  * fixed it's own GOT. It is safe to make references to externs
  * and other non-local data at this point.
  */
-static unsigned __linker_init_post_relocation(unsigned **elfdata)
+static unsigned __linker_init_post_relocation(unsigned **elfdata, unsigned linker_base)
 {
     static soinfo linker_soinfo;
 
@@ -2031,6 +1648,7 @@
     unsigned *vecs = (unsigned*) (argv + argc + 1);
     unsigned *v;
     soinfo *si;
+    int i;
     struct link_map * map;
     const char *ldpath_env = NULL;
     const char *ldpreload_env = NULL;
@@ -2095,7 +1713,7 @@
     INFO("[ android linker & debugger ]\n");
     DEBUG("%5d elfdata @ 0x%08x\n", pid, (unsigned)elfdata);
 
-    si = alloc_info(argv[0]);
+    si = soinfo_alloc(argv[0]);
     if(si == 0) {
         exit(-1);
     }
@@ -2112,15 +1730,16 @@
     _r_debug.r_map = map;
     r_debug_tail = map;
 
-        /* gdb expects the linker to be in the debug shared object list,
-         * and we need to make sure that the reported load address is zero.
-         * Without this, gdb gets the wrong idea of where rtld_db_dlactivity()
-         * is.  Don't use alloc_info(), because the linker shouldn't
+        /* 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.
          */
     strlcpy((char*) linker_soinfo.name, "/system/bin/linker", sizeof linker_soinfo.name);
     linker_soinfo.flags = 0;
-    linker_soinfo.base = 0;     // This is the important part; must be zero.
+    linker_soinfo.base = linker_base;
     insert_soinfo_into_debug_map(&linker_soinfo);
 
         /* extract information passed from the kernel */
@@ -2145,18 +1764,17 @@
      */
     int nn;
     si->base = 0;
+    si->size = phdr_table_get_load_size(si->phdr, si->phnum);
+    si->load_bias = 0;
     for ( nn = 0; nn < si->phnum; nn++ ) {
         if (si->phdr[nn].p_type == PT_PHDR) {
-            si->base = (Elf32_Addr) si->phdr - si->phdr[nn].p_vaddr;
+            si->load_bias = (Elf32_Addr)si->phdr - si->phdr[nn].p_vaddr;
+            si->base = (Elf32_Addr) si->phdr - si->phdr[nn].p_offset;
             break;
         }
     }
     si->dynamic = (unsigned *)-1;
-    si->wrprotect_start = 0xffffffff;
-    si->wrprotect_end = 0;
     si->refcount = 1;
-    si->gnu_relro_start = 0;
-    si->gnu_relro_len = 0;
 
         /* Use LD_LIBRARY_PATH if we aren't setuid/setgid */
     if (ldpath_env)
@@ -2166,14 +1784,18 @@
         parse_preloads(ldpreload_env, " :");
     }
 
-    if(link_image(si, 0)) {
+    if(soinfo_link_image(si, 0)) {
         char errmsg[] = "CANNOT LINK EXECUTABLE\n";
         write(2, __linker_dl_err_buf, strlen(__linker_dl_err_buf));
         write(2, errmsg, sizeof(errmsg));
         exit(-1);
     }
 
-    call_constructors_recursive(si);
+    for(i = 0; preloads[i] != NULL; i++) {
+        soinfo_call_constructors(preloads[i]);
+    }
+
+    soinfo_call_constructors(si);
 
 #if ALLOW_SYMBOLS_FROM_MAIN
     /* Set somain after we've loaded all the libraries in order to prevent
@@ -2249,6 +1871,32 @@
     return 0; // should never happen
 }
 
+/* Compute the load-bias of an existing executable. This shall only
+ * be used to compute the load bias of an executable or shared library
+ * that was loaded by the kernel itself.
+ *
+ * Input:
+ *    elf    -> address of ELF header, assumed to be at the start of the file.
+ * Return:
+ *    load bias, i.e. add the value of any p_vaddr in the file to get
+ *    the corresponding address in memory.
+ */
+static Elf32_Addr
+get_elf_exec_load_bias(const Elf32_Ehdr* elf)
+{
+    Elf32_Addr        offset     = elf->e_phoff;
+    const Elf32_Phdr* phdr_table = (const Elf32_Phdr*)((char*)elf + offset);
+    const Elf32_Phdr* phdr_end   = phdr_table + elf->e_phnum;
+    const Elf32_Phdr* phdr;
+
+    for (phdr = phdr_table; phdr < phdr_end; phdr++) {
+        if (phdr->p_type == PT_LOAD) {
+            return (Elf32_Addr)elf + phdr->p_offset - phdr->p_vaddr;
+        }
+    }
+    return 0;
+}
+
 /*
  * This is the entry point for the linker, called from begin.S. This
  * method is responsible for fixing the linker's own relocations, and
@@ -2268,16 +1916,14 @@
     memset(&linker_so, 0, sizeof(soinfo));
 
     linker_so.base = linker_addr;
+    linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
+    linker_so.load_bias = get_elf_exec_load_bias(elf_hdr);
     linker_so.dynamic = (unsigned *) -1;
     linker_so.phdr = phdr;
     linker_so.phnum = elf_hdr->e_phnum;
     linker_so.flags |= FLAG_LINKER;
-    linker_so.wrprotect_start = 0xffffffff;
-    linker_so.wrprotect_end = 0;
-    linker_so.gnu_relro_start = 0;
-    linker_so.gnu_relro_len = 0;
 
-    if (link_image(&linker_so, 0)) {
+    if (soinfo_link_image(&linker_so, 0)) {
         // It would be nice to print an error message, but if the linker
         // can't link itself, there's no guarantee that we'll be able to
         // call write() (because it involves a GOT reference).
@@ -2289,5 +1935,5 @@
 
     // We have successfully fixed our own relocations. It's safe to run
     // the main part of the linker now.
-    return __linker_init_post_relocation(elfdata);
+    return __linker_init_post_relocation(elfdata, linker_addr);
 }
diff --git a/linker/linker.h b/linker/linker.h
index 0c986cd..0956ac5 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -37,7 +37,23 @@
 #undef PAGE_MASK
 #undef PAGE_SIZE
 #define PAGE_SIZE 4096
-#define PAGE_MASK 4095
+#define PAGE_MASK (PAGE_SIZE-1)
+
+/* Convenience macros to make page address/offset computations more explicit */
+
+/* Returns the address of the page starting at address 'x' */
+#define PAGE_START(x)  ((x) & ~PAGE_MASK)
+
+/* Returns the offset of address 'x' in its memory page, i.e. this is the
+ * same than 'x' - PAGE_START(x) */
+#define PAGE_OFFSET(x) ((x) & PAGE_MASK)
+
+/* Returns the address of the next page after address 'x', unless 'x' is
+ * itself at the start of a page. Equivalent to:
+ *
+ *  (x == PAGE_START(x)) ? x : PAGE_START(x)+PAGE_SIZE
+ */
+#define PAGE_END(x)    PAGE_START((x) + (PAGE_SIZE-1))
 
 void debugger_init();
 const char *addr_to_name(unsigned addr);
@@ -91,7 +107,7 @@
 struct soinfo
 {
     const char name[SOINFO_NAME_LEN];
-    Elf32_Phdr *phdr;
+    const Elf32_Phdr *phdr;
     int phnum;
     unsigned entry;
     unsigned base;
@@ -101,8 +117,8 @@
 
     unsigned *dynamic;
 
-    unsigned wrprotect_start;
-    unsigned wrprotect_end;
+    unsigned unused2; // DO NOT USE, maintained for compatibility
+    unsigned unused3; // DO NOT USE, maintained for compatibility
 
     soinfo *next;
     unsigned flags;
@@ -145,9 +161,9 @@
 
     int constructors_called;
 
-    Elf32_Addr gnu_relro_start;
-    unsigned gnu_relro_len;
-
+    /* When you read a virtual address from the ELF file, add this
+     * value to get the corresponding address in the process' address space */
+    Elf32_Addr load_bias;
 };
 
 
@@ -202,13 +218,14 @@
 #endif
 
 soinfo *find_library(const char *name);
-unsigned unload_library(soinfo *si);
-Elf32_Sym *lookup_in_library(soinfo *si, const char *name);
 Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start);
 soinfo *find_containing_library(const void *addr);
-Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si);
 const char *linker_get_error(void);
-void call_constructors_recursive(soinfo *si);
+
+unsigned soinfo_unload(soinfo *si);
+Elf32_Sym *soinfo_find_symbol(soinfo* si, const void *addr);
+Elf32_Sym *soinfo_lookup(soinfo *si, const char *name);
+void soinfo_call_constructors(soinfo *si);
 
 #ifdef ANDROID_ARM_LINKER 
 typedef long unsigned int *_Unwind_Ptr;
diff --git a/linker/linker_environ.c b/linker/linker_environ.c
index b71dd80..fadcb60 100644
--- a/linker/linker_environ.c
+++ b/linker/linker_environ.c
@@ -192,13 +192,11 @@
         "TZDIR",
         "LD_AOUT_LIBRARY_PATH",
         "LD_AOUT_PRELOAD",
+        NULL
     };
 
-    const char* const* cp   = unsec_vars;
-    const char* const* endp = cp + sizeof(unsec_vars)/sizeof(unsec_vars[0]);
-
-    while (cp < endp) {
-        linker_env_unset(*cp);
-        cp++;
+    int count;
+    for (count = 0; unsec_vars[count] != NULL; count++) {
+        linker_env_unset(unsec_vars[count]);
     }
 }
diff --git a/linker/linker_format.c b/linker/linker_format.c
index 0c68a0b..cded68a 100644
--- a/linker/linker_format.c
+++ b/linker/linker_format.c
@@ -172,6 +172,21 @@
     return format_buffer(buff, bufsize, format, args);
 }
 
+/* The pthread implementation uses snprintf(). If we define it here, we
+ * avoid pulling the stdio vfprintf() implementation into the linker
+ * saving about 19KB of machine code.
+ */
+int
+snprintf(char* buff, size_t bufsize, const char* format, ...)
+{
+    va_list args;
+    int ret;
+    va_start(args, format);
+    ret = vsnprintf(buff, bufsize, format, args);
+    va_end(args);
+    return ret;
+}
+
 #if LINKER_DEBUG
 
 #if !LINKER_DEBUG_TO_LOG
diff --git a/linker/linker_phdr.c b/linker/linker_phdr.c
new file mode 100644
index 0000000..c9f194b
--- /dev/null
+++ b/linker/linker_phdr.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "linker_phdr.h"
+
+/**
+  TECHNICAL NOTE ON ELF LOADING.
+
+  An ELF file's program header table contains one or more PT_LOAD
+  segments, which corresponds to portions of the file that need to
+  be mapped into the process' address space.
+
+  Each loadable segment has the following important properties:
+
+    p_offset  -> segment file offset
+    p_filesz  -> segment file size
+    p_memsz   -> segment memory size (always >= p_filesz)
+    p_vaddr   -> segment's virtual address
+    p_flags   -> segment flags (e.g. readable, writable, executable)
+
+  We will ignore the p_paddr and p_align fields of Elf32_Phdr for now.
+
+  The loadable segments can be seen as a list of [p_vaddr ... p_vaddr+p_memsz)
+  ranges of virtual addresses. A few rules apply:
+
+  - the virtual address ranges should not overlap.
+
+  - if a segment's p_filesz is smaller than its p_memsz, the extra bytes
+    between them should always be initialized to 0.
+
+  - ranges do not necessarily start or end at page boundaries. Two distinct
+    segments can have their start and end on the same page. In this case, the
+    page inherits the mapping flags of the latter segment.
+
+  Finally, the real load addrs of each segment is not p_vaddr. Instead the
+  loader decides where to load the first segment, then will load all others
+  relative to the first one to respect the initial range layout.
+
+  For example, consider the following list:
+
+    [ offset:0,      filesz:0x4000, memsz:0x4000, vaddr:0x30000 ],
+    [ offset:0x4000, filesz:0x2000, memsz:0x8000, vaddr:0x40000 ],
+
+  This corresponds to two segments that cover these virtual address ranges:
+
+       0x30000...0x34000
+       0x40000...0x48000
+
+  If the loader decides to load the first segment at address 0xa0000000
+  then the segments' load address ranges will be:
+
+       0xa0030000...0xa0034000
+       0xa0040000...0xa0048000
+
+  In other words, all segments must be loaded at an address that has the same
+  constant offset from their p_vaddr value. This offset is computed as the
+  difference between the first segment's load address, and its p_vaddr value.
+
+  However, in practice, segments do _not_ start at page boundaries. Since we
+  can only memory-map at page boundaries, this means that the bias is
+  computed as:
+
+       load_bias = phdr0_load_address - PAGE_START(phdr0->p_vaddr)
+
+  (NOTE: The value must be used as a 32-bit unsigned integer, to deal with
+          possible wrap around UINT32_MAX for possible large p_vaddr values).
+
+  And that the phdr0_load_address must start at a page boundary, with
+  the segment's real content starting at:
+
+       phdr0_load_address + PAGE_OFFSET(phdr0->p_vaddr)
+
+  Note that ELF requires the following condition to make the mmap()-ing work:
+
+      PAGE_OFFSET(phdr0->p_vaddr) == PAGE_OFFSET(phdr0->p_offset)
+
+  The load_bias must be added to any p_vaddr value read from the ELF file to
+  determine the corresponding memory address.
+
+ **/
+
+#define MAYBE_MAP_FLAG(x,from,to)    (((x) & (from)) ? (to) : 0)
+#define PFLAGS_TO_PROT(x)            (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \
+                                      MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
+                                      MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
+
+/* Load the program header table from an ELF file into a read-only private
+ * anonymous mmap-ed block.
+ *
+ * Input:
+ *   fd           -> file descriptor
+ *   phdr_offset  -> file offset of phdr table
+ *   phdr_num     -> number of entries in the table.
+ *
+ * Output:
+ *   phdr_mmap    -> address of mmap block in memory.
+ *   phdr_memsize -> size of mmap block in memory.
+ *   phdr_table   -> address of first entry in memory.
+ *
+ * Return:
+ *   -1 on error, or 0 on success.
+ */
+int phdr_table_load(int                fd,
+                    Elf32_Addr         phdr_offset,
+                    Elf32_Half         phdr_num,
+                    void**             phdr_mmap,
+                    Elf32_Addr*        phdr_size,
+                    const Elf32_Phdr** phdr_table)
+{
+    Elf32_Addr  page_min, page_max, page_offset;
+    void*       mmap_result;
+
+    /* Just like the kernel, we only accept program header tables that
+     * are smaller than 64KB. */
+    if (phdr_num < 1 || phdr_num > 65536/sizeof(Elf32_Phdr)) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    page_min = PAGE_START(phdr_offset);
+    page_max = PAGE_END(phdr_offset + phdr_num*sizeof(Elf32_Phdr));
+    page_offset = PAGE_OFFSET(phdr_offset);
+
+    mmap_result = mmap(NULL,
+                       page_max - page_min,
+                       PROT_READ,
+                       MAP_PRIVATE,
+                       fd,
+                       page_min);
+
+    if (mmap_result == MAP_FAILED) {
+        return -1;
+    }
+
+    *phdr_mmap = mmap_result;
+    *phdr_size = page_max - page_min;
+    *phdr_table = (Elf32_Phdr*)((char*)mmap_result + page_offset);
+
+    return 0;
+}
+
+void phdr_table_unload(void* phdr_mmap, Elf32_Addr phdr_memsize)
+{
+    munmap(phdr_mmap, phdr_memsize);
+}
+
+
+/* Compute the extent of all loadable segments in an ELF program header
+ * table. This corresponds to the page-aligned size in bytes that needs to be
+ * reserved in the process' address space
+ *
+ * This returns 0 if there are no loadable segments.
+ */
+Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
+                                    int               phdr_count)
+{
+    int nn;
+
+    Elf32_Addr min_vaddr = 0xFFFFFFFFU;
+    Elf32_Addr max_vaddr = 0x00000000U;
+
+    for (nn = 0; nn < phdr_count; nn++) {
+        const Elf32_Phdr* phdr = &phdr_table[nn];
+
+        if (phdr->p_type != PT_LOAD)
+            continue;
+
+        if (phdr->p_vaddr < min_vaddr)
+            min_vaddr = phdr->p_vaddr;
+
+        if (phdr->p_vaddr + phdr->p_memsz > max_vaddr)
+            max_vaddr = phdr->p_vaddr + phdr->p_memsz;
+    }
+
+    if (min_vaddr > max_vaddr) {
+        return 0;
+    }
+
+    min_vaddr = PAGE_START(min_vaddr);
+    max_vaddr = PAGE_END(max_vaddr);
+
+    return max_vaddr - min_vaddr;
+}
+
+/* Reserve a virtual address range big enough to hold all loadable
+ * segments of a program header table. This is done by creating a
+ * private anonymous mmap() with PROT_NONE.
+ *
+ * Input:
+ *   phdr_table    -> program header table
+ *   phdr_count    -> number of entries in the tables
+ *   required_base -> for prelinked libraries, mandatory load address
+ *                    of the first loadable segment. 0 otherwise.
+ * Output:
+ *   load_start    -> first page of reserved address space range
+ *   load_size     -> size in bytes of reserved address space range
+ *   load_bias     -> load bias, as described in technical note above.
+ *
+ * Return:
+ *   0 on success, -1 otherwise. Error code in errno.
+ */
+int
+phdr_table_reserve_memory(const Elf32_Phdr* phdr_table,
+                          int               phdr_count,
+                          Elf32_Addr        required_base,
+                          void**            load_start,
+                          Elf32_Addr*       load_size,
+                          Elf32_Addr*       load_bias)
+{
+    Elf32_Addr size = phdr_table_get_load_size(phdr_table, phdr_count);
+    void*      start;
+    int        nn, mmap_flags;
+
+    if (size == 0) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
+    if (required_base != 0)
+        mmap_flags |= MAP_FIXED;
+
+    start = mmap((void*)required_base, size, PROT_NONE, mmap_flags, -1, 0);
+    if (start == MAP_FAILED) {
+        return -1;
+    }
+
+    *load_start = start;
+    *load_size  = size;
+    *load_bias  = 0;
+
+    for (nn = 0; nn < phdr_count; nn++) {
+        const Elf32_Phdr* phdr = &phdr_table[nn];
+        if (phdr->p_type == PT_LOAD) {
+            *load_bias = (Elf32_Addr)start - PAGE_START(phdr->p_vaddr);
+            break;
+        }
+    }
+    return 0;
+}
+
+/* Map all loadable segments in process' address space.
+ * This assumes you already called phdr_table_reserve_memory to
+ * reserve the address space range for the library.
+ *
+ * Input:
+ *   phdr_table    -> program header table
+ *   phdr_count    -> number of entries in the table
+ *   load_start    -> start address of reserved memory range.
+ *   load_size     -> size of reserved memory range.
+ *   load_bias     -> load offset.
+ *   fd            -> input file descriptor.
+ *
+ * Return:
+ *   0 on success, -1 otherwise. Error code in errno.
+ */
+int
+phdr_table_load_segments(const Elf32_Phdr* phdr_table,
+                         int               phdr_count,
+                         void*             load_start,
+                         Elf32_Addr        load_size,
+                         Elf32_Addr        load_bias,
+                         int               fd)
+{
+    int nn;
+
+    for (nn = 0; nn < phdr_count; nn++) {
+        const Elf32_Phdr* phdr = &phdr_table[nn];
+        void* seg_addr;
+
+        if (phdr->p_type != PT_LOAD)
+            continue;
+
+        /* Segment addresses in memory */
+        Elf32_Addr seg_start = phdr->p_vaddr + load_bias;
+        Elf32_Addr seg_end   = seg_start + phdr->p_memsz;
+
+        Elf32_Addr seg_page_start = PAGE_START(seg_start);
+        Elf32_Addr seg_page_end   = PAGE_END(seg_end);
+
+        Elf32_Addr seg_file_end   = seg_start + phdr->p_filesz;
+
+        /* File offsets */
+        Elf32_Addr file_start = phdr->p_offset;
+        Elf32_Addr file_end   = file_start + phdr->p_filesz;
+
+        Elf32_Addr file_page_start = PAGE_START(file_start);
+        Elf32_Addr file_page_end   = PAGE_END(file_end);
+
+        seg_addr = mmap((void*)seg_page_start,
+                        file_end - file_page_start,
+                        PFLAGS_TO_PROT(phdr->p_flags),
+                        MAP_FIXED|MAP_PRIVATE,
+                        fd,
+                        file_page_start);
+
+        if (seg_addr == MAP_FAILED) {
+            return -1;
+        }
+
+        /* if the segment is writable, and does not end on a page boundary,
+         * zero-fill it until the page limit. */
+        if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
+            memset((void*)seg_file_end, 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
+        }
+
+        seg_file_end = PAGE_END(seg_file_end);
+
+        /* seg_file_end is now the first page address after the file
+         * content. If seg_end is larger, we need to zero anything
+         * between them. This is done by using a private anonymous
+         * map for all extra pages.
+         */
+        if (seg_page_end > seg_file_end) {
+            void* zeromap = mmap((void*)seg_file_end,
+                                    seg_page_end - seg_file_end,
+                                    PFLAGS_TO_PROT(phdr->p_flags),
+                                    MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
+                                    -1,
+                                    0);
+            if (zeromap == MAP_FAILED) {
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+/* Used internally. Used to set the protection bits of all loaded segmments
+ * with optional extra flags (i.e. really PROT_WRITE). Used by
+ * phdr_table_protect_segments and phdr_table_unprotect_segments.
+ */
+static int
+_phdr_table_set_load_prot(const Elf32_Phdr* phdr_table,
+                          int               phdr_count,
+                          Elf32_Addr        load_bias,
+                          int               extra_prot_flags)
+{
+    const Elf32_Phdr* phdr = phdr_table;
+    const Elf32_Phdr* phdr_limit = phdr + phdr_count;
+
+    for (; phdr < phdr_limit; phdr++) {
+        if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0)
+            continue;
+
+        Elf32_Addr seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
+        Elf32_Addr seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+
+        int ret = mprotect((void*)seg_page_start,
+                           seg_page_end - seg_page_start,
+                           PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags);
+        if (ret < 0) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/* Restore the original protection modes for all loadable segments.
+ * You should only call this after phdr_table_unprotect_segments and
+ * applying all relocations.
+ *
+ * Input:
+ *   phdr_table  -> program header table
+ *   phdr_count  -> number of entires in tables
+ *   load_bias   -> load bias
+ * Return:
+ *   0 on error, -1 on failure (error code in errno).
+ */
+int
+phdr_table_protect_segments(const Elf32_Phdr* phdr_table,
+                            int               phdr_count,
+                            Elf32_Addr        load_bias)
+{
+    return _phdr_table_set_load_prot(phdr_table, phdr_count,
+                                      load_bias, 0);
+}
+
+/* Change the protection of all loaded segments in memory to writable.
+ * This is useful before performing relocations. Once completed, you
+ * will have to call phdr_table_protect_segments to restore the original
+ * protection flags on all segments.
+ *
+ * Note that some writable segments can also have their content turned
+ * to read-only by calling phdr_table_protect_gnu_relro. This is no
+ * performed here.
+ *
+ * Input:
+ *   phdr_table  -> program header table
+ *   phdr_count  -> number of entires in tables
+ *   load_bias   -> load bias
+ * Return:
+ *   0 on error, -1 on failure (error code in errno).
+ */
+int
+phdr_table_unprotect_segments(const Elf32_Phdr* phdr_table,
+                              int               phdr_count,
+                              Elf32_Addr        load_bias)
+{
+    return _phdr_table_set_load_prot(phdr_table, phdr_count,
+                                      load_bias, PROT_WRITE);
+}
+
+/* Used internally by phdr_table_protect_gnu_relro and
+ * phdr_table_unprotect_gnu_relro.
+ */
+static int
+_phdr_table_set_gnu_relro_prot(const Elf32_Phdr* phdr_table,
+                               int               phdr_count,
+                               Elf32_Addr        load_bias,
+                               int               prot_flags)
+{
+    const Elf32_Phdr* phdr = phdr_table;
+    const Elf32_Phdr* phdr_limit = phdr + phdr_count;
+
+    for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+        if (phdr->p_type != PT_GNU_RELRO)
+            continue;
+
+        /* Tricky: what happens when the relro segment does not start
+         * or end at page boundaries?. We're going to be over-protective
+         * here and put every page touched by the segment as read-only.
+         *
+         * This seems to match Ian Lance Taylor's description of the
+         * feature at http://www.airs.com/blog/archives/189.
+         *
+         * Extract:
+         *    Note that the current dynamic linker code will only work
+         *    correctly if the PT_GNU_RELRO segment starts on a page
+         *    boundary. This is because the dynamic linker rounds the
+         *    p_vaddr field down to the previous page boundary. If
+         *    there is anything on the page which should not be read-only,
+         *    the program is likely to fail at runtime. So in effect the
+         *    linker must only emit a PT_GNU_RELRO segment if it ensures
+         *    that it starts on a page boundary.
+         */
+        Elf32_Addr seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
+        Elf32_Addr seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+
+        int ret = mprotect((void*)seg_page_start,
+                           seg_page_end - seg_page_start,
+                           prot_flags);
+        if (ret < 0) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/* Apply GNU relro protection if specified by the program header. This will
+ * turn some of the pages of a writable PT_LOAD segment to read-only, as
+ * specified by one or more PT_GNU_RELRO segments. This must be always
+ * performed after relocations.
+ *
+ * NOTE: One must call phdr_table_unprotect_gnu_relro() before calling
+ *        the library's destructors, in order to ensure that the .dynamic
+ *        section is writable (as well as the .data.relro section that
+ *        might contain the content of static constant C++ objects that
+ *        needs to be destroyed).
+ *
+ * Input:
+ *   phdr_table  -> program header table
+ *   phdr_count  -> number of entires in tables
+ *   load_bias   -> load bias
+ * Return:
+ *   0 on error, -1 on failure (error code in errno).
+ */
+int
+phdr_table_protect_gnu_relro(const Elf32_Phdr* phdr_table,
+                             int               phdr_count,
+                             Elf32_Addr        load_bias)
+{
+    return _phdr_table_set_gnu_relro_prot(phdr_table,
+                                          phdr_count,
+                                          load_bias,
+                                          PROT_READ);
+}
+
+/* Un-apply GNU relro protection if specified by the program header.
+ * See comment for phdr_table_protect_gnu_relro.
+ *
+ * Input:
+ *   phdr_table  -> program header table
+ *   phdr_count  -> number of entires in tables
+ *   load_bias   -> load bias
+ * Return:
+ *   0 on error, -1 on failure (error code in errno).
+ */
+int
+phdr_table_unprotect_gnu_relro(const Elf32_Phdr* phdr_table,
+                               int               phdr_count,
+                               Elf32_Addr        load_bias)
+{
+    return _phdr_table_set_gnu_relro_prot(phdr_table,
+                                          phdr_count,
+                                          load_bias,
+                                          PROT_READ|PROT_WRITE);
+}
+
+#ifdef ANDROID_ARM_LINKER
+
+#  ifndef PT_ARM_EXIDX
+#    define PT_ARM_EXIDX    0x70000001      /* .ARM.exidx segment */
+#  endif
+
+/* Return the address and size of the .ARM.exidx section in memory,
+ * if present.
+ *
+ * Input:
+ *   phdr_table  -> program header table
+ *   phdr_count  -> number of entires in tables
+ *   load_bias   -> load bias
+ * Output:
+ *   arm_exidx       -> address of table in memory (NULL on failure).
+ *   arm_exidx_count -> number of items in table (0 on failure).
+ * Return:
+ *   0 on error, -1 on failure (_no_ error code in errno)
+ */
+int
+phdr_table_get_arm_exidx(const Elf32_Phdr* phdr_table,
+                         int               phdr_count,
+                         Elf32_Addr        load_bias,
+                         Elf32_Addr**      arm_exidx,
+                         unsigned*         arm_exidx_count)
+{
+    const Elf32_Phdr* phdr = phdr_table;
+    const Elf32_Phdr* phdr_limit = phdr + phdr_count;
+
+    for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+        if (phdr->p_type != PT_ARM_EXIDX)
+            continue;
+
+        *arm_exidx = (Elf32_Addr*)(load_bias + phdr->p_vaddr);
+        *arm_exidx_count = (unsigned)(phdr->p_memsz / 8);
+        return 0;
+    }
+    *arm_exidx = NULL;
+    *arm_exidx_count = 0;
+    return -1;
+}
+#endif /* ANDROID_ARM_LINKER */
+
+/* Return the address of the ELF file's .dynamic section in memory,
+ * or NULL if missing.
+ *
+ * Input:
+ *   phdr_table  -> program header table
+ *   phdr_count  -> number of entires in tables
+ *   load_bias   -> load bias
+ * Return:
+ *   0 on error, -1 on failure (_no_ error code in errno)
+ */
+Elf32_Addr*
+phdr_table_get_dynamic_section(const Elf32_Phdr* phdr_table,
+                               int               phdr_count,
+                               Elf32_Addr        load_bias)
+{
+    const Elf32_Phdr* phdr = phdr_table;
+    const Elf32_Phdr* phdr_limit = phdr + phdr_count;
+
+    for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+        if (phdr->p_type == PT_DYNAMIC) {
+            return (Elf32_Addr*)(load_bias + phdr->p_vaddr);
+        }
+    }
+    return NULL;
+}
+
+/* Return the address of the program header table as it appears in the loaded
+ * segments in memory. This is in contrast with the input 'phdr_table' which
+ * is temporary and will be released before the library is relocated.
+ *
+ * Input:
+ *   phdr_table  -> program header table
+ *   phdr_count  -> number of entries in tables
+ *   load_bias   -> load bias
+ * Return:
+ *   Address of loaded program header table on success (it has
+ *   'phdr_count' entries), or NULL on failure (no error code).
+ */
+const Elf32_Phdr*
+phdr_table_get_loaded_phdr(const Elf32_Phdr*   phdr_table,
+                           int                 phdr_count,
+                           Elf32_Addr          load_bias)
+{
+    const Elf32_Phdr* phdr = phdr_table;
+    const Elf32_Phdr* phdr_limit = phdr + phdr_count;
+    Elf32_Addr  loaded = 0;
+    Elf32_Addr  loaded_end;
+
+    /* If there is a PT_PHDR, use it directly */
+    for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+        if (phdr->p_type == PT_PHDR) {
+            loaded = load_bias + phdr->p_vaddr;
+            goto CHECK;
+        }
+    }
+
+    /* Otherwise, check the first loadable segment. If its file offset
+     * is 0, it starts with the ELF header, and we can trivially find the
+     * loaded program header from it. */
+    for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+        if (phdr->p_type == PT_LOAD) {
+            if (phdr->p_offset == 0) {
+                Elf32_Addr  elf_addr = load_bias + phdr->p_vaddr;
+                const Elf32_Ehdr* ehdr = (const Elf32_Ehdr*)(void*)elf_addr;
+                Elf32_Addr  offset = ehdr->e_phoff;
+                loaded = (Elf32_Addr)ehdr + offset;
+                goto CHECK;
+            }
+            break;
+        }
+    }
+
+    /* We didn't find it, let the client know. He may be able to
+     * keep a copy of the input phdr_table instead. */
+    return NULL;
+
+CHECK:
+    /* Ensure that our program header is actually within a loadable
+     * segment. This should help catch badly-formed ELF files that
+     * would cause the linker to crash later when trying to access it.
+     */
+    loaded_end = loaded + phdr_count*sizeof(Elf32_Phdr);
+
+    for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+        if (phdr->p_type != PT_LOAD)
+            continue;
+        Elf32_Addr seg_start = phdr->p_vaddr + load_bias;
+        Elf32_Addr seg_end   = phdr->p_filesz + seg_start;
+
+        if (seg_start <= loaded && loaded_end <= seg_end) {
+            return (const Elf32_Phdr*)loaded;
+        }
+    }
+    return NULL;
+}
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
new file mode 100644
index 0000000..d542e46
--- /dev/null
+++ b/linker/linker_phdr.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef LINKER_PHDR_H
+#define LINKER_PHDR_H
+
+/* Declarations related to the ELF program header table and segments.
+ *
+ * The design goal is to provide an API that is as close as possible
+ * to the ELF spec, and does not depend on linker-specific data
+ * structures (e.g. the exact layout of struct soinfo).
+ */
+
+#include "linker.h"
+
+/* See linker_phdr.c for all usage documentation */
+
+int
+phdr_table_load(int                fd,
+                Elf32_Addr         phdr_offset,
+                Elf32_Half         phdr_num,
+                void**             phdr_mmap,
+                Elf32_Addr*        phdr_size,
+                const Elf32_Phdr** phdr_table);
+
+void
+phdr_table_unload(void* phdr_mmap, Elf32_Addr phdr_memsize);
+
+Elf32_Addr
+phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
+                         int               phdr_count);
+
+int
+phdr_table_reserve_memory(const Elf32_Phdr* phdr_table,
+                          int               phdr_count,
+                          Elf32_Addr        required_base,
+                          void**            load_start,
+                          Elf32_Addr*       load_size,
+                          Elf32_Addr*       load_bias);
+
+int
+phdr_table_load_segments(const Elf32_Phdr* phdr_table,
+                         int               phdr_count,
+                         void*             load_start,
+                         Elf32_Addr        load_size,
+                         Elf32_Addr        load_bias,
+                         int               fd);
+
+int
+phdr_table_protect_segments(const Elf32_Phdr* phdr_table,
+                            int               phdr_count,
+                            Elf32_Addr        load_bias);
+
+int
+phdr_table_unprotect_segments(const Elf32_Phdr* phdr_table,
+                              int               phdr_count,
+                              Elf32_Addr        load_bias);
+
+int
+phdr_table_protect_gnu_relro(const Elf32_Phdr* phdr_table,
+                             int               phdr_count,
+                             Elf32_Addr        load_bias);
+
+int
+phdr_table_unprotect_gnu_relro(const Elf32_Phdr* phdr_table,
+                               int               phdr_count,
+                               Elf32_Addr        load_bias);
+
+const Elf32_Phdr*
+phdr_table_get_loaded_phdr(const Elf32_Phdr*   phdr_table,
+                           int                 phdr_count,
+                           Elf32_Addr          load_bias);
+
+#ifdef ANDROID_ARM_LINKER
+int
+phdr_table_get_arm_exidx(const Elf32_Phdr* phdr_table,
+                         int               phdr_count,
+                         Elf32_Addr        load_bias,
+                         Elf32_Addr**      arm_exidx,
+                         unsigned*         arm_exidix_count);
+#endif
+
+Elf32_Addr*
+phdr_table_get_dynamic_section(const Elf32_Phdr* phdr_table,
+                               int               phdr_count,
+                               Elf32_Addr        load_bias);
+
+#endif /* LINKER_PHDR_H */