Merge "Support for jemalloc to replace dlmalloc."
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 2a891b7..71d76e3 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -291,13 +291,11 @@
 int     uname(struct utsname*)  all
 mode_t  umask(mode_t)  all
 int     __reboot:reboot(int, int, int, void*)  all
-int     __syslog:syslog(int, char*, int)  all
 int     init_module(void*, unsigned long, const char*)  all
 int     delete_module(const char*, unsigned int)   all
 int     klogctl:syslog(int, char*, int)   all
 int     sysinfo(struct sysinfo*)  all
 int     personality(unsigned long)  all
-long    perf_event_open(struct perf_event_attr* attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags) all
 
 int epoll_create1(int)  all
 int epoll_ctl(int, int op, int, struct epoll_event*)  all
diff --git a/libc/arch-arm/bionic/__get_sp.S b/libc/arch-arm/bionic/__get_sp.S
index aabec6d..9ae6f24 100644
--- a/libc/arch-arm/bionic/__get_sp.S
+++ b/libc/arch-arm/bionic/__get_sp.S
@@ -28,7 +28,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__get_sp)
+ENTRY_PRIVATE(__get_sp)
   mov r0, sp
   bx lr
 END(__get_sp)
diff --git a/libc/arch-arm/syscalls/__syslog.S b/libc/arch-arm/syscalls/__syslog.S
deleted file mode 100644
index 66e761a..0000000
--- a/libc/arch-arm/syscalls/__syslog.S
+++ /dev/null
@@ -1,14 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(__syslog)
-    mov     ip, r7
-    ldr     r7, =__NR_syslog
-    swi     #0
-    mov     r7, ip
-    cmn     r0, #(MAX_ERRNO + 1)
-    bxls    lr
-    neg     r0, r0
-    b       __set_errno
-END(__syslog)
diff --git a/libc/arch-arm/syscalls/perf_event_open.S b/libc/arch-arm/syscalls/perf_event_open.S
deleted file mode 100644
index 2821ac5..0000000
--- a/libc/arch-arm/syscalls/perf_event_open.S
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(perf_event_open)
-    mov     ip, sp
-    stmfd   sp!, {r4, r5, r6, r7}
-    .cfi_def_cfa_offset 16
-    .cfi_rel_offset r4, 0
-    .cfi_rel_offset r5, 4
-    .cfi_rel_offset r6, 8
-    .cfi_rel_offset r7, 12
-    ldmfd   ip, {r4, r5, r6}
-    ldr     r7, =__NR_perf_event_open
-    swi     #0
-    ldmfd   sp!, {r4, r5, r6, r7}
-    .cfi_def_cfa_offset 0
-    cmn     r0, #(MAX_ERRNO + 1)
-    bxls    lr
-    neg     r0, r0
-    b       __set_errno
-END(perf_event_open)
diff --git a/libc/arch-arm64/bionic/__get_sp.S b/libc/arch-arm64/bionic/__get_sp.S
index d495b6a..d5e88e9 100644
--- a/libc/arch-arm64/bionic/__get_sp.S
+++ b/libc/arch-arm64/bionic/__get_sp.S
@@ -28,7 +28,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__get_sp)
+ENTRY_PRIVATE(__get_sp)
     mov x0, sp
     ret
 END(__get_sp)
diff --git a/libc/arch-arm64/bionic/__set_tls.c b/libc/arch-arm64/bionic/__set_tls.c
index 4eb3ade..0d88d11 100644
--- a/libc/arch-arm64/bionic/__set_tls.c
+++ b/libc/arch-arm64/bionic/__set_tls.c
@@ -26,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
-void __set_tls(void* tls) {
+#include <sys/cdefs.h>
+
+__LIBC_HIDDEN__ void __set_tls(void* tls) {
   asm("msr tpidr_el0, %0" : : "r" (tls));
 }
diff --git a/libc/arch-arm64/syscalls/__syslog.S b/libc/arch-arm64/syscalls/__syslog.S
deleted file mode 100644
index 2e1fb1d..0000000
--- a/libc/arch-arm64/syscalls/__syslog.S
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(__syslog)
-    stp     x29, x30, [sp, #-16]!
-    mov     x29,  sp
-    str     x8,       [sp, #-16]!
-
-    mov     x8, __NR_syslog
-    svc     #0
-
-    ldr     x8,       [sp], #16
-    ldp     x29, x30, [sp], #16
-
-    cmn     x0, #(MAX_ERRNO + 1)
-    cneg    x0, x0, hi
-    b.hi    __set_errno
-
-    ret
-END(__syslog)
-.hidden __syslog
diff --git a/libc/arch-arm64/syscalls/perf_event_open.S b/libc/arch-arm64/syscalls/perf_event_open.S
deleted file mode 100644
index 3960264..0000000
--- a/libc/arch-arm64/syscalls/perf_event_open.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(perf_event_open)
-    stp     x29, x30, [sp, #-16]!
-    mov     x29,  sp
-    str     x8,       [sp, #-16]!
-
-    mov     x8, __NR_perf_event_open
-    svc     #0
-
-    ldr     x8,       [sp], #16
-    ldp     x29, x30, [sp], #16
-
-    cmn     x0, #(MAX_ERRNO + 1)
-    cneg    x0, x0, hi
-    b.hi    __set_errno
-
-    ret
-END(perf_event_open)
diff --git a/libc/arch-mips/bionic/__get_sp.S b/libc/arch-mips/bionic/__get_sp.S
index d4b278b..5f5d32e 100644
--- a/libc/arch-mips/bionic/__get_sp.S
+++ b/libc/arch-mips/bionic/__get_sp.S
@@ -28,8 +28,7 @@
 
 #include <private/bionic_asm.h>
 
-// void* __get_sp()
-ENTRY(__get_sp)
+ENTRY_PRIVATE(__get_sp)
   move v0, sp
   j ra
 END(__get_sp)
diff --git a/libc/arch-mips/syscalls/__syslog.S b/libc/arch-mips/syscalls/__syslog.S
deleted file mode 100644
index ace69c7..0000000
--- a/libc/arch-mips/syscalls/__syslog.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(__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/perf_event_open.S b/libc/arch-mips/syscalls/perf_event_open.S
deleted file mode 100644
index a0e4416..0000000
--- a/libc/arch-mips/syscalls/perf_event_open.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(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-mips64/bionic/__get_sp.S b/libc/arch-mips64/bionic/__get_sp.S
index 8488102..5f5d32e 100644
--- a/libc/arch-mips64/bionic/__get_sp.S
+++ b/libc/arch-mips64/bionic/__get_sp.S
@@ -28,7 +28,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__get_sp)
+ENTRY_PRIVATE(__get_sp)
   move v0, sp
   j ra
 END(__get_sp)
diff --git a/libc/arch-mips64/syscalls/__syslog.S b/libc/arch-mips64/syscalls/__syslog.S
deleted file mode 100644
index 70eed3a..0000000
--- a/libc/arch-mips64/syscalls/__syslog.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(__syslog)
-    .set push
-    .set noreorder
-    li v0, __NR_syslog
-    syscall
-    bnez a3, 1f
-    move a0, v0
-    j ra
-    nop
-1:
-    move t0, ra
-    bal     2f
-    nop
-2:
-    .cpsetup ra, t1, 2b
-    LA t9,__set_errno
-    .cpreturn
-    j t9
-    move ra, t0
-    .set pop
-END(__syslog)
-.hidden __syslog
diff --git a/libc/arch-mips64/syscalls/perf_event_open.S b/libc/arch-mips64/syscalls/perf_event_open.S
deleted file mode 100644
index d796a16..0000000
--- a/libc/arch-mips64/syscalls/perf_event_open.S
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(perf_event_open)
-    .set push
-    .set noreorder
-    li v0, __NR_perf_event_open
-    syscall
-    bnez a3, 1f
-    move a0, v0
-    j ra
-    nop
-1:
-    move t0, ra
-    bal     2f
-    nop
-2:
-    .cpsetup ra, t1, 2b
-    LA t9,__set_errno
-    .cpreturn
-    j t9
-    move ra, t0
-    .set pop
-END(perf_event_open)
diff --git a/libc/arch-x86/bionic/__get_sp.S b/libc/arch-x86/bionic/__get_sp.S
index 31ec6bc..aea6ac6 100644
--- a/libc/arch-x86/bionic/__get_sp.S
+++ b/libc/arch-x86/bionic/__get_sp.S
@@ -28,7 +28,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__get_sp)
+ENTRY_PRIVATE(__get_sp)
   mov  %esp, %eax
   ret
 END(__get_sp)
diff --git a/libc/arch-x86/bionic/__set_tls.c b/libc/arch-x86/bionic/__set_tls.c
index 722ec6f..38ed3c9 100644
--- a/libc/arch-x86/bionic/__set_tls.c
+++ b/libc/arch-x86/bionic/__set_tls.c
@@ -57,7 +57,7 @@
   result->useable = 1;
 }
 
-int __set_tls(void* ptr) {
+__LIBC_HIDDEN__ int __set_tls(void* ptr) {
   struct user_desc tls_descriptor;
   __init_user_desc(&tls_descriptor, true, ptr);
 
diff --git a/libc/arch-x86/syscalls/__syslog.S b/libc/arch-x86/syscalls/__syslog.S
deleted file mode 100644
index 1da01be..0000000
--- a/libc/arch-x86/syscalls/__syslog.S
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(__syslog)
-    pushl   %ebx
-    pushl   %ecx
-    pushl   %edx
-    .cfi_def_cfa_offset 12
-    .cfi_rel_offset ebx, 0
-    .cfi_rel_offset ecx, 4
-    .cfi_rel_offset edx, 8
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
-    movl    $__NR_syslog, %eax
-    int     $0x80
-    cmpl    $-MAX_ERRNO, %eax
-    jb      1f
-    negl    %eax
-    pushl   %eax
-    call    __set_errno
-    addl    $4, %esp
-    orl     $-1, %eax
-1:
-    popl    %edx
-    popl    %ecx
-    popl    %ebx
-    ret
-END(__syslog)
diff --git a/libc/arch-x86/syscalls/perf_event_open.S b/libc/arch-x86/syscalls/perf_event_open.S
deleted file mode 100644
index ebbe1f0..0000000
--- a/libc/arch-x86/syscalls/perf_event_open.S
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(perf_event_open)
-    pushl   %ebx
-    pushl   %ecx
-    pushl   %edx
-    pushl   %esi
-    pushl   %edi
-    .cfi_def_cfa_offset 20
-    .cfi_rel_offset ebx, 0
-    .cfi_rel_offset ecx, 4
-    .cfi_rel_offset edx, 8
-    .cfi_rel_offset esi, 12
-    .cfi_rel_offset edi, 16
-    mov     24(%esp), %ebx
-    mov     28(%esp), %ecx
-    mov     32(%esp), %edx
-    mov     36(%esp), %esi
-    mov     40(%esp), %edi
-    movl    $__NR_perf_event_open, %eax
-    int     $0x80
-    cmpl    $-MAX_ERRNO, %eax
-    jb      1f
-    negl    %eax
-    pushl   %eax
-    call    __set_errno
-    addl    $4, %esp
-    orl     $-1, %eax
-1:
-    popl    %edi
-    popl    %esi
-    popl    %edx
-    popl    %ecx
-    popl    %ebx
-    ret
-END(perf_event_open)
diff --git a/libc/arch-x86_64/bionic/__get_sp.S b/libc/arch-x86_64/bionic/__get_sp.S
index 9cc18a9..49a2406 100644
--- a/libc/arch-x86_64/bionic/__get_sp.S
+++ b/libc/arch-x86_64/bionic/__get_sp.S
@@ -28,7 +28,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__get_sp)
+ENTRY_PRIVATE(__get_sp)
   mov  %rsp, %rax
   ret
 END(__get_sp)
diff --git a/libc/arch-x86_64/bionic/__set_tls.c b/libc/arch-x86_64/bionic/__set_tls.c
index cc7a5f4..10fd36f 100644
--- a/libc/arch-x86_64/bionic/__set_tls.c
+++ b/libc/arch-x86_64/bionic/__set_tls.c
@@ -26,11 +26,12 @@
  * SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
 #include <asm/prctl.h>
 #include <stdint.h>
 
 extern int __arch_prctl(int, unsigned long);
 
-int __set_tls(void* ptr) {
+__LIBC_HIDDEN__ int __set_tls(void* ptr) {
   return __arch_prctl(ARCH_SET_FS, (uintptr_t) ptr);
 }
diff --git a/libc/arch-x86_64/syscalls/__syslog.S b/libc/arch-x86_64/syscalls/__syslog.S
deleted file mode 100644
index f710025..0000000
--- a/libc/arch-x86_64/syscalls/__syslog.S
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(__syslog)
-    movl    $__NR_syslog, %eax
-    syscall
-    cmpq    $-MAX_ERRNO, %rax
-    jb      1f
-    negl    %eax
-    movl    %eax, %edi
-    call    __set_errno
-    orq     $-1, %rax
-1:
-    ret
-END(__syslog)
-.hidden __syslog
diff --git a/libc/arch-x86_64/syscalls/perf_event_open.S b/libc/arch-x86_64/syscalls/perf_event_open.S
deleted file mode 100644
index d9fc71e..0000000
--- a/libc/arch-x86_64/syscalls/perf_event_open.S
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(perf_event_open)
-    movq    %rcx, %r10
-    movl    $__NR_perf_event_open, %eax
-    syscall
-    cmpq    $-MAX_ERRNO, %rax
-    jb      1f
-    negl    %eax
-    movl    %eax, %edi
-    call    __set_errno
-    orq     $-1, %rax
-1:
-    ret
-END(perf_event_open)
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index 43b213f..3e112a0 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -73,6 +73,13 @@
   '__strrchr_chk',
   '__umask_chk'
 ])
+# Some symbols are used to implement public macros.
+macro_stuff = set([
+  '__assert2',
+  '__errno',
+  '__fe_dfl_env',
+  '__get_h_errno',
+])
 # bionic exposes various Linux features that glibc doesn't.
 linux_stuff = set([
   'getauxval',
@@ -114,7 +121,8 @@
 
 print
 print 'in bionic but not glibc:'
-for symbol in sorted((bionic - bsd_stuff - FORTIFY_stuff - linux_stuff - std_stuff - weird_stuff).difference(glibc)):
+allowed_stuff = (bsd_stuff | FORTIFY_stuff | linux_stuff | macro_stuff | std_stuff | weird_stuff)
+for symbol in sorted((bionic - allowed_stuff).difference(glibc)):
   print symbol
 
 sys.exit(0)
diff --git a/libc/tools/zoneinfo/update-tzdata.py b/libc/tools/zoneinfo/update-tzdata.py
index 8956136..3dcb210 100755
--- a/libc/tools/zoneinfo/update-tzdata.py
+++ b/libc/tools/zoneinfo/update-tzdata.py
@@ -1,36 +1,40 @@
 #!/usr/bin/python
 
-"""Updates the tzdata file."""
+"""Updates the timezone data held in bionic and ICU."""
 
 import ftplib
+import glob
 import httplib
 import os
 import re
+import shutil
 import subprocess
 import sys
 import tarfile
 import tempfile
 
-# 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):
-  print "Couldn't find bionic/libc/tools/zoneinfo!"
-  sys.exit(1)
-if not os.path.isdir(bionic_libc_zoneinfo_dir):
-  print "Couldn't find bionic/libc/zoneinfo!"
-  sys.exit(1)
-
-print 'Found bionic in %s...' % bionic_dir
-
-
 regions = ['africa', 'antarctica', 'asia', 'australasia', 'backward',
            'etcetera', 'europe', 'northamerica', 'southamerica']
 
+def CheckDirExists(dir, dirname):
+  if not os.path.isdir(dir):
+    print "Couldn't find %s (%s)!" % (dirname, dir)
+    sys.exit(1)
+
+bionic_libc_tools_zoneinfo_dir = os.path.realpath(os.path.dirname(sys.argv[0]))
+
+# Find the bionic directory, searching upward from this script.
+bionic_dir = os.path.realpath('%s/../../..' % bionic_libc_tools_zoneinfo_dir)
+bionic_libc_zoneinfo_dir = '%s/libc/zoneinfo' % bionic_dir
+CheckDirExists(bionic_libc_zoneinfo_dir, 'bionic/libc/zoneinfo')
+CheckDirExists(bionic_libc_tools_zoneinfo_dir, 'bionic/libc/tools/zoneinfo')
+print 'Found bionic in %s ...' % bionic_dir
+
+# Find the icu4c directory.
+icu_dir = os.path.realpath('%s/../external/icu4c' % bionic_dir)
+CheckDirExists(icu_dir, 'external/icu4c')
+print 'Found icu in %s ...' % icu_dir
+
 
 def GetCurrentTzDataVersion():
   return open('%s/tzdata' % bionic_libc_zoneinfo_dir).read().split('\x00', 1)[0]
@@ -65,50 +69,81 @@
   print 'Created temporary directory "%s"...' % tmp_dir
 
 
-def FtpRetrieve(ftp, filename):
+def FtpRetrieveFile(ftp, filename):
   ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
 
 
-def FtpUpgrade(ftp, data_filename):
+def FtpRetrieveFileAndSignature(ftp, data_filename):
   """Downloads and repackages the given data from the given FTP server."""
-  SwitchToNewTemporaryDirectory()
-
   print 'Downloading data...'
-  FtpRetrieve(ftp, data_filename)
+  FtpRetrieveFile(ftp, data_filename)
 
   print 'Downloading signature...'
   signature_filename = '%s.asc' % data_filename
-  FtpRetrieve(ftp, signature_filename)
-
-  ExtractAndCompile(data_filename)
+  FtpRetrieveFile(ftp, signature_filename)
 
 
-def HttpRetrieve(http, path, output_filename):
+def HttpRetrieveFile(http, path, output_filename):
   http.request("GET", path)
   f = open(output_filename, 'wb')
   f.write(http.getresponse().read())
   f.close()
 
 
-def HttpUpgrade(http, data_filename):
+def HttpRetrieveFileAndSignature(http, data_filename):
   """Downloads and repackages the given data from the given HTTP server."""
-  SwitchToNewTemporaryDirectory()
-
   path = "/time-zones/repository/releases/%s" % data_filename
 
   print 'Downloading data...'
-  HttpRetrieve(http, path, data_filename)
+  HttpRetrieveFile(http, path, data_filename)
 
   print 'Downloading signature...'
   signature_filename = '%s.asc' % data_filename
-  HttpRetrieve(http, "%s.asc" % path, signature_filename)
-
-  ExtractAndCompile(data_filename)
+  HttpRetrievefile(http, "%s.asc" % path, signature_filename)
 
 
-def ExtractAndCompile(data_filename):
-  new_version = re.search('(tzdata.+)\\.tar\\.gz', data_filename).group(1)
+def BuildIcuToolsAndData(data_filename):
+  # Keep track of the original cwd so we can go back to it at the end.
+  original_working_dir = os.getcwd()
 
+  # Create a directory to run 'make' from.
+  icu_working_dir = '%s/icu' % original_working_dir
+  os.mkdir(icu_working_dir)
+  os.chdir(icu_working_dir)
+
+  # Build the ICU tools.
+  print 'Configuring ICU tools...'
+  subprocess.check_call(['%s/runConfigureICU' % icu_dir, 'Linux'])
+  print 'Making ICU tools...'
+  subprocess.check_call(['make', '-j6'])
+
+  # Run the ICU tools.
+  os.chdir('tools/tzcode')
+  shutil.copyfile('%s/%s' % (original_working_dir, data_filename), data_filename)
+  print 'Making ICU data...'
+  subprocess.check_call(['make'])
+
+  # Copy the output files to their ultimate destination.
+  icu_txt_data_dir = '%s/data/misc' % icu_dir
+  print 'Copying zoneinfo64.txt to %s ...' % icu_txt_data_dir
+  shutil.copy('zoneinfo64.txt', icu_txt_data_dir)
+
+  os.chdir(icu_working_dir)
+  icu_dat_data_dir = '%s/stubdata' % icu_dir
+  datfiles = glob.glob('data/out/tmp/icudt??l.dat')
+  if len(datfiles) != 1:
+    print 'ERROR: Unexpectedly found %d .dat files (%s). Halting.' % (len(datfiles), datfiles)
+    sys.exit(1)
+
+  datfile = datfiles[0]
+  print 'Copying %s to %s ...' % (datfile, icu_dat_data_dir)
+  shutil.copy(datfile, icu_dat_data_dir)
+
+  # Switch back to the original working cwd.
+  os.chdir(original_working_dir)
+
+
+def CheckSignature(data_filename):
   signature_filename = '%s.asc' % data_filename
   print 'Verifying signature...'
   # If this fails for you, you probably need to import Paul Eggert's public key:
@@ -116,6 +151,10 @@
   subprocess.check_call(['gpg', '--trusted-key=ED97E90E62AA7E34', '--verify',
                          signature_filename, data_filename])
 
+
+def BuildBionicToolsAndData(data_filename):
+  new_version = re.search('(tzdata.+)\\.tar\\.gz', data_filename).group(1)
+
   print 'Extracting...'
   os.mkdir('extracted')
   tar = tarfile.open(data_filename, 'r')
@@ -175,10 +214,16 @@
   for filename in tzdata_filenames:
     if filename > current_filename:
       print 'Found new tzdata: %s' % filename
+      SwitchToNewTemporaryDirectory()
       if use_ftp:
-        FtpUpgrade(ftp, filename)
+        FtpRetrieveFileAndSignature(ftp, filename)
       else:
-        HttpUpgrade(http, filename)
+        HttpRetrieveFileAndSignature(http, filename)
+
+      CheckSignature(filename)
+      BuildIcuToolsAndData(filename)
+      BuildBionicToolsAndData(filename)
+      print 'Look in %s and %s for new data files' % (bionic_dir, icu_dir)
       sys.exit(0)
 
   print 'You already have the latest tzdata (%s)!' % current_version
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 8ef1212..7e3b3f4 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -102,7 +102,7 @@
   ElfW(Sym)* sym = NULL;
   if (handle == RTLD_DEFAULT) {
     sym = dlsym_linear_lookup(symbol, &found, NULL);
-  } else if (handle == RTLD_NEXT) {
+  } else if (handle == RTLD_NEXT || handle == (void*)0xffffffffL) {
     void* caller_addr = __builtin_return_address(0);
     soinfo* si = find_containing_library(caller_addr);