Merge "Remove /proc/cpuinfo parsing"
diff --git a/adb/.clang-format b/adb/.clang-format
index 2b83a1f..0395c8e 100644
--- a/adb/.clang-format
+++ b/adb/.clang-format
@@ -4,8 +4,8 @@
 
 CommentPragmas: NOLINT:.*
 DerivePointerAlignment: false
-IndentWidth: 2
+IndentWidth: 4
 PointerAlignment: Left
-TabWidth: 2
+TabWidth: 4
 UseTab: Never
 PenaltyExcessCharacter: 32
diff --git a/adb/Android.mk b/adb/Android.mk
index 8171611..8d38077 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -90,7 +90,7 @@
 LOCAL_CFLAGS := -DADB_HOST=0 $(LIBADB_CFLAGS)
 LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS)
 LOCAL_STATIC_LIBRARIES := libadbd
-LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
+LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
 include $(BUILD_NATIVE_TEST)
 
 include $(CLEAR_VARS)
@@ -98,12 +98,11 @@
 LOCAL_MODULE := adb_test
 LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
 LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.cpp
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES := liblog libbase
 LOCAL_STATIC_LIBRARIES := \
     libadb \
     libcrypto_static \
     libcutils \
-    libutils \
 
 ifeq ($(HOST_OS),linux)
   LOCAL_LDLIBS += -lrt -ldl -lpthread
@@ -200,7 +199,7 @@
 LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
 endif
 
-ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
 endif
 
diff --git a/adb/adb.h b/adb/adb.h
index 1aeac6b..749515c 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -298,9 +298,6 @@
 
 #if !ADB_HOST
 void framebuffer_service(int fd, void *cookie);
-// Allow enable-verity to write to system and vendor block devices
-int make_block_device_writable(const char* dev);
-void remount_service(int fd, void *cookie);
 void set_verity_enabled_state_service(int fd, void* cookie);
 #endif
 
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 1487287..e0425ad 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -23,7 +23,6 @@
 
 extern int auth_enabled;
 
-void adb_auth_init(void);
 int adb_auth_keygen(const char* filename);
 void adb_auth_verified(atransport *t);
 
@@ -40,6 +39,7 @@
 
 #if ADB_HOST
 
+void adb_auth_init(void);
 int adb_auth_sign(void *key, const unsigned char* token, size_t token_size,
                   unsigned char* sig);
 void *adb_auth_nextkey(void *current);
@@ -58,6 +58,8 @@
 static inline void *adb_auth_nextkey(void *current) { return NULL; }
 static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return 0; }
 
+void adbd_auth_init(void);
+void adbd_cloexec_auth_socket();
 int adb_auth_generate_token(void *token, size_t token_size);
 int adb_auth_verify(uint8_t* token, uint8_t* sig, int siglen);
 void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
diff --git a/adb/adb_auth_client.cpp b/adb/adb_auth_client.cpp
index deb0a5d..5dadcd9 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adb_auth_client.cpp
@@ -249,19 +249,23 @@
     }
 }
 
-void adb_auth_init(void)
-{
-    int fd, ret;
-
-    fd = android_get_control_socket("adbd");
-    if (fd < 0) {
+void adbd_cloexec_auth_socket() {
+    int fd = android_get_control_socket("adbd");
+    if (fd == -1) {
         D("Failed to get adbd socket\n");
         return;
     }
     fcntl(fd, F_SETFD, FD_CLOEXEC);
+}
 
-    ret = listen(fd, 4);
-    if (ret < 0) {
+void adbd_auth_init(void) {
+    int fd = android_get_control_socket("adbd");
+    if (fd == -1) {
+        D("Failed to get adbd socket\n");
+        return;
+    }
+
+    if (listen(fd, 4) == -1) {
         D("Failed to listen on '%d'\n", fd);
         return;
     }
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 330d9ce..0c69bc9 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -24,7 +24,7 @@
 
 #include <string>
 
-#include "utils/file.h"
+#include "base/file.h"
 
 class TemporaryFile {
  public:
@@ -55,7 +55,7 @@
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
 
-  ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno);
+  ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
   ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
 
   // Test reading the whole file.
@@ -69,7 +69,7 @@
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
 
-  ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno);
+  ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
   ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
 
   // Test that not having enough data will fail.
@@ -83,7 +83,7 @@
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
 
-  ASSERT_TRUE(android::WriteStringToFd(input, tf.fd)) << strerror(errno);
+  ASSERT_TRUE(android::base::WriteStringToFd(input, tf.fd)) << strerror(errno);
   ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
 
   // Test reading a partial file.
@@ -106,7 +106,7 @@
   ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
 
   std::string s;
-  ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+  ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
   EXPECT_STREQ(expected, s.c_str());
 }
 
@@ -123,7 +123,7 @@
   expected.pop_back();
 
   std::string s;
-  ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+  ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
   EXPECT_EQ(expected, s);
 }
 
@@ -137,6 +137,6 @@
   ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
 
   std::string s;
-  ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+  ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
   EXPECT_STREQ(str, s.c_str());
 }
diff --git a/adb/adb_main.cpp b/adb/adb_main.cpp
index b0816ce..1d9cc3b 100644
--- a/adb/adb_main.cpp
+++ b/adb/adb_main.cpp
@@ -273,10 +273,14 @@
         exit(1);
     }
 #else
+    // We need to call this even if auth isn't enabled because the file
+    // descriptor will always be open.
+    adbd_cloexec_auth_socket();
+
     property_get("ro.adb.secure", value, "0");
     auth_enabled = !strcmp(value, "1");
     if (auth_enabled)
-        adb_auth_init();
+        adbd_auth_init();
 
     // Our external storage path may be different than apps, since
     // we aren't able to bind mount after dropping root.
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index ecaab83..4538b04 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -43,7 +43,8 @@
 static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
 
 int find_sync_dirs(const char *srcarg,
-        char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
+        char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
+        char **oem_srcdir_out);
 int install_app(transport_type transport, const char* serial, int argc,
                 const char** argv);
 int install_multiple_app(transport_type transport, const char* serial, int argc,
@@ -206,7 +207,7 @@
         "  adb get-serialno             - prints: <serial-number>\n"
         "  adb get-devpath              - prints: <device-path>\n"
         "  adb status-window            - continuously print device status for a specified device\n"
-        "  adb remount                  - remounts the /system and /vendor (if present) partitions on the device read-write\n"
+        "  adb remount                  - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
         "  adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
         "  adb reboot-bootloader        - reboots the device into the bootloader\n"
         "  adb root                     - restarts the adbd daemon with root permissions\n"
@@ -222,9 +223,9 @@
         "adb sync notes: adb sync [ <directory> ]\n"
         "  <localdir> can be interpreted in several ways:\n"
         "\n"
-        "  - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n"
+        "  - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.\n"
         "\n"
-        "  - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
+        "  - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
         "    is updated.\n"
         "\n"
         "environmental variables:\n"
@@ -1633,7 +1634,8 @@
     }
     else if (!strcmp(argv[0], "sync")) {
         const char* srcarg;
-        char *android_srcpath, *data_srcpath, *vendor_srcpath;
+        char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
+
         int listonly = 0;
 
         int ret;
@@ -1653,18 +1655,22 @@
         } else {
             return usage();
         }
-        ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
+        ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
+                &oem_srcpath);
         if (ret != 0) return usage();
 
-        if (android_srcpath != NULL)
-            ret = do_sync_sync(android_srcpath, "/system", listonly);
+        if (system_srcpath != NULL)
+            ret = do_sync_sync(system_srcpath, "/system", listonly);
         if (ret == 0 && vendor_srcpath != NULL)
             ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
+        if(ret == 0 && oem_srcpath != NULL)
+            ret = do_sync_sync(oem_srcpath, "/oem", listonly);
         if (ret == 0 && data_srcpath != NULL)
             ret = do_sync_sync(data_srcpath, "/data", listonly);
 
-        free(android_srcpath);
+        free(system_srcpath);
         free(vendor_srcpath);
+        free(oem_srcpath);
         free(data_srcpath);
         return ret;
     }
@@ -1770,49 +1776,60 @@
 }
 
 int find_sync_dirs(const char *srcarg,
-        char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
+        char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
+        char **oem_srcdir_out)
 {
-    char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
+    char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
     struct stat st;
 
     if(srcarg == NULL) {
-        android_srcdir = product_file("system");
+        system_srcdir = product_file("system");
         data_srcdir = product_file("data");
         vendor_srcdir = product_file("vendor");
-        /* Check if vendor partition exists */
+        oem_srcdir = product_file("oem");
+        // Check if vendor partition exists.
         if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
             vendor_srcdir = NULL;
+        // Check if oem partition exists.
+        if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
+            oem_srcdir = NULL;
     } else {
-        /* srcarg may be "data", "system" or NULL.
-         * if srcarg is NULL, then both data and system are synced
-         */
+        // srcarg may be "data", "system", "vendor", "oem" or NULL.
+        // If srcarg is NULL, then all partitions are synced.
         if(strcmp(srcarg, "system") == 0) {
-            android_srcdir = product_file("system");
+            system_srcdir = product_file("system");
         } else if(strcmp(srcarg, "data") == 0) {
             data_srcdir = product_file("data");
         } else if(strcmp(srcarg, "vendor") == 0) {
             vendor_srcdir = product_file("vendor");
+        } else if(strcmp(srcarg, "oem") == 0) {
+            oem_srcdir = product_file("oem");
         } else {
-            /* It's not "system", "vendor", or "data".
-             */
+            // It's not "system", "data", "vendor", or "oem".
             return 1;
         }
     }
 
-    if(android_srcdir_out != NULL)
-        *android_srcdir_out = android_srcdir;
+    if(system_srcdir_out != NULL)
+        *system_srcdir_out = system_srcdir;
     else
-        free(android_srcdir);
+        free(system_srcdir);
 
     if(vendor_srcdir_out != NULL)
         *vendor_srcdir_out = vendor_srcdir;
     else
         free(vendor_srcdir);
 
+    if(oem_srcdir_out != NULL)
+        *oem_srcdir_out = oem_srcdir;
+    else
+        free(oem_srcdir);
+
     if(data_srcdir_out != NULL)
-            *data_srcdir_out = data_srcdir;
-        else
-            free(data_srcdir);
+        *data_srcdir_out = data_srcdir;
+    else
+        free(data_srcdir);
+
     return 0;
 }
 
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 45d33db..eeb2a9c 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -587,6 +587,7 @@
         FATAL("fde %p not created by fdevent_create()\n", fde);
     }
     fdevent_remove(fde);
+    free(fde);
 }
 
 void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 2864b38..ac01678 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -33,15 +33,11 @@
 #include "file_sync_service.h"
 #include "private/android_filesystem_config.h"
 
-/* TODO: use fs_config to configure permissions on /data */
-static bool is_on_system(const char *name) {
-    const char *SYSTEM = "/system/";
-    return (strncmp(SYSTEM, name, strlen(SYSTEM)) == 0);
-}
-
-static bool is_on_vendor(const char *name) {
-    const char *VENDOR = "/vendor/";
-    return (strncmp(VENDOR, name, strlen(VENDOR)) == 0);
+static bool should_use_fs_config(const char* path) {
+    // TODO: use fs_config to configure permissions on /data.
+    return strncmp("/system/", path, strlen("/system/")) == 0 ||
+           strncmp("/vendor/", path, strlen("/vendor/")) == 0 ||
+           strncmp("/oem/", path, strlen("/oem/")) == 0;
 }
 
 static int mkdirs(char *name)
@@ -59,7 +55,7 @@
         x = adb_dirstart(x);
         if(x == 0) return 0;
         *x = 0;
-        if (is_on_system(name) || is_on_vendor(name)) {
+        if (should_use_fs_config(name)) {
             fs_config(name, 1, &uid, &gid, &mode, &cap);
         }
         ret = adb_mkdir(name, mode);
@@ -368,7 +364,7 @@
     if(*tmp == '/') {
         tmp++;
     }
-    if (is_on_system(path) || is_on_vendor(path)) {
+    if (should_use_fs_config(path)) {
         fs_config(tmp, 0, &uid, &gid, &mode, &cap);
     }
     return handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index 414b316..a83d5b1 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -23,6 +23,8 @@
 #include <sys/mount.h>
 #include <unistd.h>
 
+#include <string>
+
 #include "sysdeps.h"
 
 #define  TRACE_TAG  TRACE_ADB
@@ -32,10 +34,10 @@
 
 static int system_ro = 1;
 static int vendor_ro = 1;
+static int oem_ro = 1;
 
 /* Returns the device used to mount a directory in /proc/mounts */
-static char *find_mount(const char *dir)
-{
+static std::string find_mount(const char *dir) {
     FILE* fp;
     struct mntent* mentry;
     char* device = NULL;
@@ -45,7 +47,7 @@
     }
     while ((mentry = getmntent(fp)) != NULL) {
         if (strcmp(dir, mentry->mnt_dir) == 0) {
-            device = strdup(mentry->mnt_fsname);
+            device = mentry->mnt_fsname;
             break;
         }
     }
@@ -53,64 +55,53 @@
     return device;
 }
 
-static int hasVendorPartition()
-{
-    struct stat info;
-    if (!lstat("/vendor", &info))
-        if ((info.st_mode & S_IFMT) == S_IFDIR)
-          return true;
-    return false;
+static bool has_partition(const char* path) {
+    struct stat sb;
+    return (lstat(path, &sb) == 0 && S_ISDIR(sb.st_mode));
 }
 
-int make_block_device_writable(const char* dev)
-{
-    int fd = -1;
+int make_block_device_writable(const std::string& dev) {
+    int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
+    if (fd == -1) {
+        return -1;
+    }
+
+    int result = -1;
     int OFF = 0;
-    int rc = -1;
-
-    if (!dev)
-        goto errout;
-
-    fd = unix_open(dev, O_RDONLY | O_CLOEXEC);
-    if (fd < 0)
-        goto errout;
-
-    if (ioctl(fd, BLKROSET, &OFF)) {
-        goto errout;
+    if (!ioctl(fd, BLKROSET, &OFF)) {
+        result = 0;
     }
+    adb_close(fd);
 
-    rc = 0;
-
-errout:
-    if (fd >= 0) {
-        adb_close(fd);
-    }
-    return rc;
+    return result;
 }
 
-/* Init mounts /system as read only, remount to enable writes. */
-static int remount(const char* dir, int* dir_ro)
-{
-    char *dev = 0;
-    int rc = -1;
-
-    dev = find_mount(dir);
-
-    if (!dev || make_block_device_writable(dev)) {
-        goto errout;
+// Init mounts /system as read only, remount to enable writes.
+static int remount(const char* dir, int* dir_ro) {
+    std::string dev(find_mount(dir));
+    if (dev.empty() || make_block_device_writable(dev)) {
+        return -1;
     }
 
-    rc = mount(dev, dir, "none", MS_REMOUNT, NULL);
+    int rc = mount(dev.c_str(), dir, "none", MS_REMOUNT, NULL);
     *dir_ro = rc;
-
-errout:
-    free(dev);
     return rc;
 }
 
-void remount_service(int fd, void *cookie)
-{
-    char buffer[200];
+static bool remount_partition(int fd, const char* partition, int* ro) {
+  if (!has_partition(partition)) {
+    return true;
+  }
+  if (remount(partition, ro)) {
+    char buf[200];
+    snprintf(buf, sizeof(buf), "remount of %s failed: %s\n", partition, strerror(errno));
+    WriteStringFully(fd, buf);
+    return false;
+  }
+  return true;
+}
+
+void remount_service(int fd, void* cookie) {
     char prop_buf[PROPERTY_VALUE_MAX];
 
     if (getuid() != 0) {
@@ -133,6 +124,7 @@
     if (system_verified || vendor_verified) {
         // Allow remount but warn of likely bad effects
         bool both = system_verified && vendor_verified;
+        char buffer[200];
         snprintf(buffer, sizeof(buffer),
                  "dm_verity is enabled on the %s%s%s partition%s.\n",
                  system_verified ? "system" : "",
@@ -147,23 +139,12 @@
         WriteStringFully(fd, buffer);
     }
 
-    if (remount("/system", &system_ro)) {
-        snprintf(buffer, sizeof(buffer), "remount of system failed: %s\n",strerror(errno));
-        WriteStringFully(fd, buffer);
-    }
+    bool success = true;
+    success &= remount_partition(fd, "/system", &system_ro);
+    success &= remount_partition(fd, "/vendor", &vendor_ro);
+    success &= remount_partition(fd, "/oem", &oem_ro);
 
-    if (hasVendorPartition()) {
-        if (remount("/vendor", &vendor_ro)) {
-            snprintf(buffer, sizeof(buffer), "remount of vendor failed: %s\n",strerror(errno));
-            WriteStringFully(fd, buffer);
-        }
-    }
-
-    if (!system_ro && (!vendor_ro || !hasVendorPartition()))
-        WriteStringFully(fd, "remount succeeded\n");
-    else {
-        WriteStringFully(fd, "remount failed\n");
-    }
+    WriteStringFully(fd, success ? "remount succeeded\n" : "remount failed\n");
 
     adb_close(fd);
 }
diff --git a/adb/remount_service.h b/adb/remount_service.h
new file mode 100644
index 0000000..e1763cf
--- /dev/null
+++ b/adb/remount_service.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 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 _REMOUNT_SERVICE_H_
+#define _REMOUNT_SERVICE_H_
+
+#include <string>
+
+int make_block_device_writable(const std::string&);
+void remount_service(int, void*);
+
+#endif
diff --git a/adb/services.cpp b/adb/services.cpp
index 600eb30..e7bf6b0 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -38,6 +38,7 @@
 #include "adb.h"
 #include "adb_io.h"
 #include "file_sync_service.h"
+#include "remount_service.h"
 #include "transport.h"
 
 typedef struct stinfo stinfo;
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index 85637f2..139b074 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -26,6 +26,7 @@
 #include "cutils/properties.h"
 #include "ext4_sb.h"
 #include "fs_mgr.h"
+#include "remount_service.h"
 #include "sysdeps.h"
 
 #define FSTAB_PREFIX "/fstab."
diff --git a/base/.clang-format b/base/.clang-format
new file mode 100644
index 0000000..2b83a1f
--- /dev/null
+++ b/base/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 2
+PointerAlignment: Left
+TabWidth: 2
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/base/Android.mk b/base/Android.mk
new file mode 100644
index 0000000..0e1a9b6
--- /dev/null
+++ b/base/Android.mk
@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2015 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+libbase_src_files := \
+    file.cpp \
+    stringprintf.cpp \
+    strings.cpp \
+
+libbase_test_src_files := \
+    file_test.cpp \
+    stringprintf_test.cpp \
+    strings_test.cpp \
+
+libbase_cppflags := \
+    -Wall \
+    -Wextra \
+    -Werror \
+
+# Device
+# ------------------------------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(libbase_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase
+LOCAL_CLANG := true
+LOCAL_WHOLE_STATIC_LIBRARIES := libbase
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+include $(BUILD_SHARED_LIBRARY)
+
+# Host
+# ------------------------------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(libbase_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase
+LOCAL_CLANG := true
+LOCAL_WHOLE_STATIC_LIBRARIES := libbase
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+# Tests
+# ------------------------------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase_test
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(libbase_test_src_files)
+LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_SHARED_LIBRARIES := libbase
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase_test
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(libbase_test_src_files)
+LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_SHARED_LIBRARIES := libbase
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_HOST_NATIVE_TEST)
diff --git a/base/CPPLINT.cfg b/base/CPPLINT.cfg
new file mode 100644
index 0000000..5ee068e
--- /dev/null
+++ b/base/CPPLINT.cfg
@@ -0,0 +1,2 @@
+set noparent
+filter=-build/header_guard
diff --git a/libutils/file.cpp b/base/file.cpp
similarity index 68%
rename from libutils/file.cpp
rename to base/file.cpp
index 0690bc2..118071e 100644
--- a/libutils/file.cpp
+++ b/base/file.cpp
@@ -14,19 +14,23 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "utils.file"
-#include <cutils/log.h>
-
-#include "utils/file.h"
+#include "base/file.h"
 
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include <utils/Compat.h> // For TEMP_FAILURE_RETRY on Darwin.
+#include <string>
 
-bool android::ReadFdToString(int fd, std::string* content) {
+#include "base/macros.h"  // For TEMP_FAILURE_RETRY on Darwin.
+#define LOG_TAG "base.file"
+#include "cutils/log.h"
+
+namespace android {
+namespace base {
+
+bool ReadFdToString(int fd, std::string* content) {
   content->clear();
 
   char buf[BUFSIZ];
@@ -37,10 +41,11 @@
   return (n == 0) ? true : false;
 }
 
-bool android::ReadFileToString(const std::string& path, std::string* content) {
+bool ReadFileToString(const std::string& path, std::string* content) {
   content->clear();
 
-  int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+  int fd =
+      TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
   if (fd == -1) {
     return false;
   }
@@ -49,7 +54,7 @@
   return result;
 }
 
-bool android::WriteStringToFd(const std::string& content, int fd) {
+bool WriteStringToFd(const std::string& content, int fd) {
   const char* p = content.data();
   size_t left = content.size();
   while (left > 0) {
@@ -72,18 +77,18 @@
 }
 
 #if !defined(_WIN32)
-bool android::WriteStringToFile(const std::string& content, const std::string& path,
-                                mode_t mode, uid_t owner, gid_t group) {
-  int fd = TEMP_FAILURE_RETRY(open(path.c_str(),
-                                   O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
-                                   mode));
+bool WriteStringToFile(const std::string& content, const std::string& path,
+                       mode_t mode, uid_t owner, gid_t group) {
+  int fd = TEMP_FAILURE_RETRY(
+      open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+           mode));
   if (fd == -1) {
     ALOGE("android::WriteStringToFile open failed: %s", strerror(errno));
     return false;
   }
 
-  // We do an explicit fchmod here because we assume that the caller really meant what they
-  // said and doesn't want the umask-influenced mode.
+  // We do an explicit fchmod here because we assume that the caller really
+  // meant what they said and doesn't want the umask-influenced mode.
   if (fchmod(fd, mode) == -1) {
     ALOGE("android::WriteStringToFile fchmod failed: %s", strerror(errno));
     return CleanUpAfterFailedWrite(path);
@@ -101,10 +106,10 @@
 }
 #endif
 
-bool android::WriteStringToFile(const std::string& content, const std::string& path) {
-  int fd = TEMP_FAILURE_RETRY(open(path.c_str(),
-                                   O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
-                                   DEFFILEMODE));
+bool WriteStringToFile(const std::string& content, const std::string& path) {
+  int fd = TEMP_FAILURE_RETRY(
+      open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+           DEFFILEMODE));
   if (fd == -1) {
     return false;
   }
@@ -113,3 +118,6 @@
   TEMP_FAILURE_RETRY(close(fd));
   return result || CleanUpAfterFailedWrite(path);
 }
+
+}  // namespace base
+}  // namespace android
diff --git a/libutils/tests/file_test.cpp b/base/file_test.cpp
similarity index 72%
rename from libutils/tests/file_test.cpp
rename to base/file_test.cpp
index cea18b6..34b8755 100644
--- a/libutils/tests/file_test.cpp
+++ b/base/file_test.cpp
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-#include "utils/file.h"
+#include "base/file.h"
+
+#include <gtest/gtest.h>
 
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <gtest/gtest.h>
+
+#include <string>
 
 class TemporaryFile {
  public:
@@ -48,14 +51,14 @@
 TEST(file, ReadFileToString_ENOENT) {
   std::string s("hello");
   errno = 0;
-  ASSERT_FALSE(android::ReadFileToString("/proc/does-not-exist", &s));
+  ASSERT_FALSE(android::base::ReadFileToString("/proc/does-not-exist", &s));
   EXPECT_EQ(ENOENT, errno);
-  EXPECT_EQ("", s); // s was cleared.
+  EXPECT_EQ("", s);  // s was cleared.
 }
 
 TEST(file, ReadFileToString_success) {
   std::string s("hello");
-  ASSERT_TRUE(android::ReadFileToString("/proc/version", &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s)) << errno;
   EXPECT_GT(s.length(), 6U);
   EXPECT_EQ('\n', s[s.length() - 1]);
   s[5] = 0;
@@ -65,34 +68,36 @@
 TEST(file, WriteStringToFile) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
-  ASSERT_TRUE(android::WriteStringToFile("abc", tf.filename)) << errno;
+  ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename)) << errno;
   std::string s;
-  ASSERT_TRUE(android::ReadFileToString(tf.filename, &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
   EXPECT_EQ("abc", s);
 }
 
 TEST(file, WriteStringToFile2) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
-  ASSERT_TRUE(android::WriteStringToFile("abc", tf.filename, 0660, getuid(), getgid())) << errno;
+  ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename, 0660,
+                                               getuid(), getgid()))
+      << errno;
   struct stat sb;
   ASSERT_EQ(0, stat(tf.filename, &sb));
   ASSERT_EQ(0660U, (sb.st_mode & ~S_IFMT));
   ASSERT_EQ(getuid(), sb.st_uid);
   ASSERT_EQ(getgid(), sb.st_gid);
   std::string s;
-  ASSERT_TRUE(android::ReadFileToString(tf.filename, &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
   EXPECT_EQ("abc", s);
 }
 
 TEST(file, WriteStringToFd) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
-  ASSERT_TRUE(android::WriteStringToFd("abc", tf.fd));
+  ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
 
   ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << errno;
 
   std::string s;
-  ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << errno;
   EXPECT_EQ("abc", s);
 }
diff --git a/include/utils/file.h b/base/include/base/file.h
similarity index 89%
rename from include/utils/file.h
rename to base/include/base/file.h
index a80afb1..ef97742 100644
--- a/include/utils/file.h
+++ b/base/include/base/file.h
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef UTILS_FILE_H
-#define UTILS_FILE_H
+#ifndef BASE_FILE_H
+#define BASE_FILE_H
 
-#include <string>
 #include <sys/stat.h>
+#include <string>
 
 namespace android {
+namespace base {
 
 bool ReadFdToString(int fd, std::string* content);
 bool ReadFileToString(const std::string& path, std::string* content);
@@ -33,6 +34,7 @@
                        mode_t mode, uid_t owner, gid_t group);
 #endif
 
-} // namespace android
+}  // namespace base
+}  // namespace android
 
-#endif
+#endif  // BASE_FILE_H
diff --git a/base/include/base/macros.h b/base/include/base/macros.h
new file mode 100644
index 0000000..b1ce7c6
--- /dev/null
+++ b/base/include/base/macros.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2015 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 UTILS_MACROS_H
+#define UTILS_MACROS_H
+
+#include <stddef.h>  // for size_t
+#include <unistd.h>  // for TEMP_FAILURE_RETRY
+
+// bionic and glibc both have TEMP_FAILURE_RETRY, but eg Mac OS' libc doesn't.
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(exp)            \
+  ({                                       \
+    decltype(exp) _rc;                     \
+    do {                                   \
+      _rc = (exp);                         \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc;                                   \
+  })
+#endif
+
+// A macro to disallow the copy constructor and operator= functions
+// This must be placed in the private: declarations for a class.
+//
+// For disallowing only assign or copy, delete the relevant operator or
+// constructor, for example:
+// void operator=(const TypeName&) = delete;
+// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
+// semantically, one should either use disallow both or neither. Try to
+// avoid these in new code.
+//
+// When building with C++11 toolchains, just use the language support
+// for explicitly deleted methods.
+#if __cplusplus >= 201103L
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete
+#else
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+#endif
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+//
+// This should be used in the private: declarations for a class
+// that wants to prevent anyone from instantiating it. This is
+// especially useful for classes containing only static methods.
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+  TypeName();                                    \
+  DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+// The arraysize(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example.  If you use arraysize on
+// a pointer by mistake, you will get a compile-time error.
+//
+// One caveat is that arraysize() doesn't accept any array of an
+// anonymous type or a type defined inside a function.  In these rare
+// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below.  This is
+// due to a limitation in C++'s template system.  The limitation might
+// eventually be removed, but it hasn't happened yet.
+
+// This template function declaration is used in defining arraysize.
+// Note that the function doesn't need an implementation, as we only
+// use its type.
+template <typename T, size_t N>
+char(&ArraySizeHelper(T(&array)[N]))[N];  // NOLINT(readability/casting)
+
+#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+
+// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize,
+// but can be used on anonymous types or types defined inside
+// functions.  It's less safe than arraysize as it accepts some
+// (although not all) pointers.  Therefore, you should use arraysize
+// whenever possible.
+//
+// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type
+// size_t.
+//
+// ARRAYSIZE_UNSAFE catches a few type errors.  If you see a compiler error
+//
+//   "warning: division by zero in ..."
+//
+// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer.
+// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays.
+//
+// The following comments are on the implementation details, and can
+// be ignored by the users.
+//
+// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in
+// the array) and sizeof(*(arr)) (the # of bytes in one array
+// element).  If the former is divisible by the latter, perhaps arr is
+// indeed an array, in which case the division result is the # of
+// elements in the array.  Otherwise, arr cannot possibly be an array,
+// and we generate a compiler error to prevent the code from
+// compiling.
+//
+// Since the size of bool is implementation-defined, we need to cast
+// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
+// result has type size_t.
+//
+// This macro is not perfect as it wrongfully accepts certain
+// pointers, namely where the pointer size is divisible by the pointee
+// size.  Since all our code has to go through a 32-bit compiler,
+// where a pointer is 4 bytes, this means all pointers to a type whose
+// size is 3 or greater than 4 will be (righteously) rejected.
+#define ARRAYSIZE_UNSAFE(a)     \
+  ((sizeof(a) / sizeof(*(a))) / \
+    static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+#define LIKELY(x) __builtin_expect((x), true)
+#define UNLIKELY(x) __builtin_expect((x), false)
+
+#define WARN_UNUSED __attribute__((warn_unused_result))
+
+// A deprecated function to call to create a false use of the parameter, for
+// example:
+//   int foo(int x) { UNUSED(x); return 10; }
+// to avoid compiler warnings. Going forward we prefer ATTRIBUTE_UNUSED.
+template <typename... T>
+void UNUSED(const T&...) {
+}
+
+// An attribute to place on a parameter to a function, for example:
+//   int foo(int x ATTRIBUTE_UNUSED) { return 10; }
+// to avoid compiler warnings.
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+
+// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
+// between switch labels:
+//  switch (x) {
+//    case 40:
+//    case 41:
+//      if (truth_is_out_there) {
+//        ++x;
+//        FALLTHROUGH_INTENDED;  // Use instead of/along with annotations in
+//                               // comments.
+//      } else {
+//        return x;
+//      }
+//    case 42:
+//      ...
+//
+//  As shown in the example above, the FALLTHROUGH_INTENDED macro should be
+//  followed by a semicolon. It is designed to mimic control-flow statements
+//  like 'break;', so it can be placed in most places where 'break;' can, but
+//  only if there are no statements on the execution path between it and the
+//  next switch label.
+//
+//  When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is
+//  expanded to [[clang::fallthrough]] attribute, which is analysed when
+//  performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough').
+//  See clang documentation on language extensions for details:
+//  http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
+//
+//  When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
+//  effect on diagnostics.
+//
+//  In either case this macro has no effect on runtime behavior and performance
+//  of code.
+#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning)
+#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#define FALLTHROUGH_INTENDED [[clang::fallthrough]]  // NOLINT
+#endif
+#endif
+
+#ifndef FALLTHROUGH_INTENDED
+#define FALLTHROUGH_INTENDED \
+  do {                       \
+  } while (0)
+#endif
+
+#endif  // UTILS_MACROS_H
diff --git a/include/utils/stringprintf.h b/base/include/base/stringprintf.h
similarity index 82%
rename from include/utils/stringprintf.h
rename to base/include/base/stringprintf.h
index e7dbac7..195c1de 100644
--- a/include/utils/stringprintf.h
+++ b/base/include/base/stringprintf.h
@@ -14,25 +14,27 @@
  * limitations under the License.
  */
 
-#ifndef UTILS_STRINGPRINTF_H_
-#define UTILS_STRINGPRINTF_H_
+#ifndef BASE_STRINGPRINTF_H
+#define BASE_STRINGPRINTF_H
 
 #include <stdarg.h>
 #include <string>
 
 namespace android {
+namespace base {
 
 // Returns a string corresponding to printf-like formatting of the arguments.
 std::string StringPrintf(const char* fmt, ...)
-        __attribute__((__format__(__printf__, 1, 2)));
+    __attribute__((__format__(__printf__, 1, 2)));
 
 // Appends a printf-like formatting of the arguments to 'dst'.
 void StringAppendF(std::string* dst, const char* fmt, ...)
-        __attribute__((__format__(__printf__, 2, 3)));
+    __attribute__((__format__(__printf__, 2, 3)));
 
 // Appends a printf-like formatting of the arguments to 'dst'.
 void StringAppendV(std::string* dst, const char* format, va_list ap);
 
+}  // namespace base
 }  // namespace android
 
-#endif
+#endif  // BASE_STRINGPRINTF_H
diff --git a/base/include/base/strings.h b/base/include/base/strings.h
new file mode 100644
index 0000000..5ddfbbd
--- /dev/null
+++ b/base/include/base/strings.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 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 BASE_STRINGS_H
+#define BASE_STRINGS_H
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace base {
+
+// Splits a string using the given separator character into a vector of strings.
+// Empty strings will be omitted.
+void Split(const std::string& s, char separator,
+           std::vector<std::string>* result);
+
+// Trims whitespace off both ends of the given string.
+std::string Trim(const std::string& s);
+
+// Joins a vector of strings into a single string, using the given separator.
+template <typename StringT>
+std::string Join(const std::vector<StringT>& strings, char separator);
+
+// Tests whether 's' starts with 'prefix'.
+bool StartsWith(const std::string& s, const char* prefix);
+
+// Tests whether 's' ends with 'suffix'.
+bool EndsWith(const std::string& s, const char* suffix);
+
+}  // namespace base
+}  // namespace android
+
+#endif  // BASE_STRINGS_H
diff --git a/libutils/stringprintf.cpp b/base/stringprintf.cpp
similarity index 84%
rename from libutils/stringprintf.cpp
rename to base/stringprintf.cpp
index 5eaa293..d55ff52 100644
--- a/libutils/stringprintf.cpp
+++ b/base/stringprintf.cpp
@@ -14,11 +14,16 @@
  * limitations under the License.
  */
 
-#include <utils/stringprintf.h>
+#include "base/stringprintf.h"
 
 #include <stdio.h>
 
-void android::StringAppendV(std::string* dst, const char* format, va_list ap) {
+#include <string>
+
+namespace android {
+namespace base {
+
+void StringAppendV(std::string* dst, const char* format, va_list ap) {
   // First try with a small fixed size buffer
   char space[1024];
 
@@ -45,7 +50,7 @@
 
   // Increase the buffer size to the size requested by vsnprintf,
   // plus one for the closing \0.
-  int length = result+1;
+  int length = result + 1;
   char* buf = new char[length];
 
   // Restore the va_list before we use it again
@@ -60,7 +65,7 @@
   delete[] buf;
 }
 
-std::string android::StringPrintf(const char* fmt, ...) {
+std::string StringPrintf(const char* fmt, ...) {
   va_list ap;
   va_start(ap, fmt);
   std::string result;
@@ -69,9 +74,12 @@
   return result;
 }
 
-void android::StringAppendF(std::string* dst, const char* format, ...) {
+void StringAppendF(std::string* dst, const char* format, ...) {
   va_list ap;
   va_start(ap, format);
   StringAppendV(dst, format, ap);
   va_end(ap);
 }
+
+}  // namespace base
+}  // namespace android
diff --git a/libutils/tests/stringprintf_test.cpp b/base/stringprintf_test.cpp
similarity index 76%
rename from libutils/tests/stringprintf_test.cpp
rename to base/stringprintf_test.cpp
index f995452..5cc2086 100644
--- a/libutils/tests/stringprintf_test.cpp
+++ b/base/stringprintf_test.cpp
@@ -14,25 +14,27 @@
  * limitations under the License.
  */
 
-#include <utils/stringprintf.h>
+#include "base/stringprintf.h"
 
 #include <gtest/gtest.h>
 
+#include <string>
+
 TEST(StringPrintfTest, HexSizeT) {
   size_t size = 0x00107e59;
-  EXPECT_EQ("00107e59", android::StringPrintf("%08zx", size));
-  EXPECT_EQ("0x00107e59", android::StringPrintf("0x%08zx", size));
+  EXPECT_EQ("00107e59", android::base::StringPrintf("%08zx", size));
+  EXPECT_EQ("0x00107e59", android::base::StringPrintf("0x%08zx", size));
 }
 
 TEST(StringPrintfTest, StringAppendF) {
   std::string s("a");
-  android::StringAppendF(&s, "b");
+  android::base::StringAppendF(&s, "b");
   EXPECT_EQ("ab", s);
 }
 
 TEST(StringPrintfTest, Errno) {
   errno = 123;
-  android::StringPrintf("hello %s", "world");
+  android::base::StringPrintf("hello %s", "world");
   EXPECT_EQ(123, errno);
 }
 
@@ -40,7 +42,7 @@
   char* buf = new char[n + 1];
   memset(buf, 'x', n);
   buf[n] = '\0';
-  std::string s(android::StringPrintf("%s", buf));
+  std::string s(android::base::StringPrintf("%s", buf));
   EXPECT_EQ(buf, s);
   delete[] buf;
 }
diff --git a/base/strings.cpp b/base/strings.cpp
new file mode 100644
index 0000000..224a46f
--- /dev/null
+++ b/base/strings.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "base/strings.h"
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace base {
+
+void Split(const std::string& s, char separator,
+           std::vector<std::string>* result) {
+  const char* p = s.data();
+  const char* end = p + s.size();
+  while (p != end) {
+    if (*p == separator) {
+      ++p;
+    } else {
+      const char* start = p;
+      while (++p != end && *p != separator) {
+        // Skip to the next occurrence of the separator.
+      }
+      result->push_back(std::string(start, p - start));
+    }
+  }
+}
+
+std::string Trim(const std::string& s) {
+  std::string result;
+
+  if (s.size() == 0) {
+    return result;
+  }
+
+  size_t start_index = 0;
+  size_t end_index = s.size() - 1;
+
+  // Skip initial whitespace.
+  while (start_index < s.size()) {
+    if (!isspace(s[start_index])) {
+      break;
+    }
+    start_index++;
+  }
+
+  // Skip terminating whitespace.
+  while (end_index >= start_index) {
+    if (!isspace(s[end_index])) {
+      break;
+    }
+    end_index--;
+  }
+
+  // All spaces, no beef.
+  if (end_index < start_index) {
+    return "";
+  }
+  // Start_index is the first non-space, end_index is the last one.
+  return s.substr(start_index, end_index - start_index + 1);
+}
+
+template <typename StringT>
+std::string Join(const std::vector<StringT>& strings, char separator) {
+  if (strings.empty()) {
+    return "";
+  }
+
+  std::string result(strings[0]);
+  for (size_t i = 1; i < strings.size(); ++i) {
+    result += separator;
+    result += strings[i];
+  }
+  return result;
+}
+
+// Explicit instantiations.
+template std::string Join<std::string>(const std::vector<std::string>& strings,
+                                       char separator);
+template std::string Join<const char*>(const std::vector<const char*>& strings,
+                                       char separator);
+
+bool StartsWith(const std::string& s, const char* prefix) {
+  return s.compare(0, strlen(prefix), prefix) == 0;
+}
+
+bool EndsWith(const std::string& s, const char* suffix) {
+  size_t suffix_length = strlen(suffix);
+  size_t string_length = s.size();
+  if (suffix_length > string_length) {
+    return false;
+  }
+  size_t offset = string_length - suffix_length;
+  return s.compare(offset, suffix_length, suffix) == 0;
+}
+
+}  // namespace base
+}  // namespace android
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
new file mode 100644
index 0000000..824598d
--- /dev/null
+++ b/base/strings_test.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "base/strings.h"
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+TEST(strings, split_empty) {
+  std::vector<std::string> parts;
+  android::base::Split("", '\0', &parts);
+  ASSERT_EQ(0U, parts.size());
+}
+
+TEST(strings, split_single) {
+  std::vector<std::string> parts;
+  android::base::Split("foo", ',', &parts);
+  ASSERT_EQ(1U, parts.size());
+  ASSERT_EQ("foo", parts[0]);
+}
+
+TEST(strings, split_simple) {
+  std::vector<std::string> parts;
+  android::base::Split("foo,bar,baz", ',', &parts);
+  ASSERT_EQ(3U, parts.size());
+  ASSERT_EQ("foo", parts[0]);
+  ASSERT_EQ("bar", parts[1]);
+  ASSERT_EQ("baz", parts[2]);
+}
+
+TEST(strings, split_with_empty_part) {
+  std::vector<std::string> parts;
+  android::base::Split("foo,,bar", ',', &parts);
+  ASSERT_EQ(2U, parts.size());
+  ASSERT_EQ("foo", parts[0]);
+  ASSERT_EQ("bar", parts[1]);
+}
+
+TEST(strings, trim_empty) {
+  ASSERT_EQ("", android::base::Trim(""));
+}
+
+TEST(strings, trim_already_trimmed) {
+  ASSERT_EQ("foo", android::base::Trim("foo"));
+}
+
+TEST(strings, trim_left) {
+  ASSERT_EQ("foo", android::base::Trim(" foo"));
+}
+
+TEST(strings, trim_right) {
+  ASSERT_EQ("foo", android::base::Trim("foo "));
+}
+
+TEST(strings, trim_both) {
+  ASSERT_EQ("foo", android::base::Trim(" foo "));
+}
+
+TEST(strings, trim_no_trim_middle) {
+  ASSERT_EQ("foo bar", android::base::Trim("foo bar"));
+}
+
+TEST(strings, trim_other_whitespace) {
+  ASSERT_EQ("foo", android::base::Trim("\v\tfoo\n\f"));
+}
+
+TEST(strings, join_nothing) {
+  std::vector<std::string> list = {};
+  ASSERT_EQ("", android::base::Join(list, ','));
+}
+
+TEST(strings, join_single) {
+  std::vector<std::string> list = {"foo"};
+  ASSERT_EQ("foo", android::base::Join(list, ','));
+}
+
+TEST(strings, join_simple) {
+  std::vector<std::string> list = {"foo", "bar", "baz"};
+  ASSERT_EQ("foo,bar,baz", android::base::Join(list, ','));
+}
+
+TEST(strings, join_separator_in_vector) {
+  std::vector<std::string> list = {",", ","};
+  ASSERT_EQ(",,,", android::base::Join(list, ','));
+}
+
+TEST(strings, startswith_empty) {
+  ASSERT_FALSE(android::base::StartsWith("", "foo"));
+  ASSERT_TRUE(android::base::StartsWith("", ""));
+}
+
+TEST(strings, startswith_simple) {
+  ASSERT_TRUE(android::base::StartsWith("foo", ""));
+  ASSERT_TRUE(android::base::StartsWith("foo", "f"));
+  ASSERT_TRUE(android::base::StartsWith("foo", "fo"));
+  ASSERT_TRUE(android::base::StartsWith("foo", "foo"));
+}
+
+TEST(strings, startswith_prefix_too_long) {
+  ASSERT_FALSE(android::base::StartsWith("foo", "foobar"));
+}
+
+TEST(strings, startswith_contains_prefix) {
+  ASSERT_FALSE(android::base::StartsWith("foobar", "oba"));
+  ASSERT_FALSE(android::base::StartsWith("foobar", "bar"));
+}
+
+TEST(strings, endswith_empty) {
+  ASSERT_FALSE(android::base::EndsWith("", "foo"));
+  ASSERT_TRUE(android::base::EndsWith("", ""));
+}
+
+TEST(strings, endswith_simple) {
+  ASSERT_TRUE(android::base::EndsWith("foo", ""));
+  ASSERT_TRUE(android::base::EndsWith("foo", "o"));
+  ASSERT_TRUE(android::base::EndsWith("foo", "oo"));
+  ASSERT_TRUE(android::base::EndsWith("foo", "foo"));
+}
+
+TEST(strings, endswith_prefix_too_long) {
+  ASSERT_FALSE(android::base::EndsWith("foo", "foobar"));
+}
+
+TEST(strings, endswith_contains_prefix) {
+  ASSERT_FALSE(android::base::EndsWith("foobar", "oba"));
+  ASSERT_FALSE(android::base::EndsWith("foobar", "foo"));
+}
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 8cc4682..dd53296 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -5,6 +5,7 @@
 LOCAL_SRC_FILES:= \
     backtrace.cpp \
     debuggerd.cpp \
+    elf_utils.cpp \
     getevent.cpp \
     tombstone.cpp \
     utility.cpp \
@@ -28,6 +29,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
     libbacktrace \
+    libbase \
     libcutils \
     liblog \
     libselinux \
@@ -38,7 +40,6 @@
 LOCAL_MODULE_STEM_32 := debuggerd
 LOCAL_MODULE_STEM_64 := debuggerd64
 LOCAL_MULTILIB := both
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/debuggerd/elf_utils.cpp b/debuggerd/elf_utils.cpp
new file mode 100644
index 0000000..764b9db
--- /dev/null
+++ b/debuggerd/elf_utils.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "DEBUG"
+
+#include <elf.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <string>
+
+#include <backtrace/Backtrace.h>
+#include <base/stringprintf.h>
+#include <log/log.h>
+
+#include "elf_utils.h"
+
+template <typename HdrType, typename PhdrType, typename NhdrType>
+static bool get_build_id(
+    Backtrace* backtrace, uintptr_t base_addr, uint8_t* e_ident, std::string* build_id) {
+  HdrType hdr;
+
+  memcpy(&hdr.e_ident[0], e_ident, EI_NIDENT);
+
+  // First read the rest of the header.
+  if (backtrace->Read(base_addr + EI_NIDENT, reinterpret_cast<uint8_t*>(&hdr) + EI_NIDENT,
+                      sizeof(HdrType) - EI_NIDENT) != sizeof(HdrType) - EI_NIDENT) {
+    return false;
+  }
+
+  for (size_t i = 0; i < hdr.e_phnum; i++) {
+    PhdrType phdr;
+    if (backtrace->Read(base_addr + hdr.e_phoff + i * hdr.e_phentsize,
+                        reinterpret_cast<uint8_t*>(&phdr), sizeof(phdr)) != sizeof(phdr)) {
+      return false;
+    }
+    // Looking for the .note.gnu.build-id note.
+    if (phdr.p_type == PT_NOTE) {
+      size_t hdr_size = phdr.p_filesz;
+      uintptr_t addr = base_addr + phdr.p_offset;
+      while (hdr_size >= sizeof(NhdrType)) {
+        NhdrType nhdr;
+        if (backtrace->Read(addr, reinterpret_cast<uint8_t*>(&nhdr), sizeof(nhdr)) != sizeof(nhdr)) {
+          return false;
+        }
+        addr += sizeof(nhdr);
+        if (nhdr.n_type == NT_GNU_BUILD_ID) {
+          // Skip the name (which is the owner and should be "GNU").
+          addr += nhdr.n_namesz;
+          uint8_t build_id_data[128];
+          if (nhdr.n_namesz > sizeof(build_id_data)) {
+            ALOGE("Possible corrupted note, name size value is too large: %u",
+                  nhdr.n_namesz);
+            return false;
+          }
+          if (backtrace->Read(addr, build_id_data, nhdr.n_descsz) != nhdr.n_descsz) {
+            return false;
+          }
+
+          build_id->clear();
+          for (size_t bytes = 0; bytes < nhdr.n_descsz; bytes++) {
+            *build_id += android::base::StringPrintf("%02x", build_id_data[bytes]);
+          }
+
+          return true;
+        } else {
+          // Move past the extra note data.
+          hdr_size -= sizeof(nhdr);
+          size_t skip_bytes = nhdr.n_namesz + nhdr.n_descsz;
+          addr += skip_bytes;
+          if (hdr_size < skip_bytes) {
+            break;
+          }
+          hdr_size -= skip_bytes;
+        }
+      }
+    }
+  }
+  return false;
+}
+
+bool elf_get_build_id(Backtrace* backtrace, uintptr_t addr, std::string* build_id) {
+  // Read and verify the elf magic number first.
+  uint8_t e_ident[EI_NIDENT];
+  if (backtrace->Read(addr, e_ident, SELFMAG) != SELFMAG) {
+    return false;
+  }
+
+  if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
+    return false;
+  }
+
+  // Read the rest of EI_NIDENT.
+  if (backtrace->Read(addr + SELFMAG, e_ident + SELFMAG, EI_NIDENT - SELFMAG) != EI_NIDENT - SELFMAG) {
+    return false;
+  }
+
+  if (e_ident[EI_CLASS] == ELFCLASS32) {
+    return get_build_id<Elf32_Ehdr, Elf32_Phdr, Elf32_Nhdr>(backtrace, addr, e_ident, build_id);
+  } else if (e_ident[EI_CLASS] == ELFCLASS64) {
+    return get_build_id<Elf64_Ehdr, Elf64_Phdr, Elf64_Nhdr>(backtrace, addr, e_ident, build_id);
+  }
+
+  return false;
+}
diff --git a/debuggerd/elf_utils.h b/debuggerd/elf_utils.h
new file mode 100644
index 0000000..11d0a43
--- /dev/null
+++ b/debuggerd/elf_utils.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 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 _DEBUGGERD_ELF_UTILS_H
+#define _DEBUGGERD_ELF_UTILS_H
+
+#include <stdint.h>
+#include <string>
+
+class Backtrace;
+
+bool elf_get_build_id(Backtrace*, uintptr_t, std::string*);
+
+#endif // _DEBUGGERD_ELF_UTILS_H
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index e927ea3..094ab48 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -34,6 +34,7 @@
 
 #include <private/android_filesystem_config.h>
 
+#include <base/stringprintf.h>
 #include <cutils/properties.h>
 #include <log/log.h>
 #include <log/logger.h>
@@ -46,9 +47,12 @@
 
 #include <UniquePtr.h>
 
+#include <string>
+
+#include "backtrace.h"
+#include "elf_utils.h"
 #include "machine.h"
 #include "tombstone.h"
-#include "backtrace.h"
 
 #define STACK_WORDS 16
 
@@ -234,47 +238,36 @@
 
 static void dump_stack_segment(
     Backtrace* backtrace, log_t* log, uintptr_t* sp, size_t words, int label) {
+  // Read the data all at once.
+  word_t stack_data[words];
+  size_t bytes_read = backtrace->Read(*sp, reinterpret_cast<uint8_t*>(&stack_data[0]), sizeof(word_t) * words);
+  words = bytes_read / sizeof(word_t);
+  std::string line;
   for (size_t i = 0; i < words; i++) {
-    word_t stack_content;
-    if (!backtrace->ReadWord(*sp, &stack_content)) {
-      break;
+    line = "    ";
+    if (i == 0 && label >= 0) {
+      // Print the label once.
+      line += android::base::StringPrintf("#%02d  ", label);
+    } else {
+      line += "     ";
     }
+    line += android::base::StringPrintf("%" PRIPTR "  %" PRIPTR, *sp, stack_data[i]);
 
     backtrace_map_t map;
-    backtrace->FillInMap(stack_content, &map);
-    std::string map_name;
-    if (BacktraceMap::IsValid(map) && map.name.length() > 0) {
-      map_name = "  " + map.name;
-    }
-    uintptr_t offset = 0;
-    std::string func_name(backtrace->GetFunctionName(stack_content, &offset));
-    if (!func_name.empty()) {
-      if (!i && label >= 0) {
+    backtrace->FillInMap(stack_data[i], &map);
+    if (BacktraceMap::IsValid(map) && !map.name.empty()) {
+      line += "  " + map.name;
+      uintptr_t offset = 0;
+      std::string func_name(backtrace->GetFunctionName(stack_data[i], &offset));
+      if (!func_name.empty()) {
+        line += " (" + func_name;
         if (offset) {
-          _LOG(log, logtype::STACK, "    #%02d  %" PRIPTR "  %" PRIPTR "%s (%s+%" PRIuPTR ")\n",
-               label, *sp, stack_content, map_name.c_str(), func_name.c_str(), offset);
-        } else {
-          _LOG(log, logtype::STACK, "    #%02d  %" PRIPTR "  %" PRIPTR "%s (%s)\n",
-               label, *sp, stack_content, map_name.c_str(), func_name.c_str());
+          line += android::base::StringPrintf("+%" PRIuPTR, offset);
         }
-      } else {
-        if (offset) {
-          _LOG(log, logtype::STACK, "         %" PRIPTR "  %" PRIPTR "%s (%s+%" PRIuPTR ")\n",
-               *sp, stack_content, map_name.c_str(), func_name.c_str(), offset);
-        } else {
-          _LOG(log, logtype::STACK, "         %" PRIPTR "  %" PRIPTR "%s (%s)\n",
-               *sp, stack_content, map_name.c_str(), func_name.c_str());
-        }
-      }
-    } else {
-      if (!i && label >= 0) {
-        _LOG(log, logtype::STACK, "    #%02d  %" PRIPTR "  %" PRIPTR "%s\n",
-             label, *sp, stack_content, map_name.c_str());
-      } else {
-        _LOG(log, logtype::STACK, "         %" PRIPTR "  %" PRIPTR "%s\n",
-             *sp, stack_content, map_name.c_str());
+        line += ')';
       }
     }
+    _LOG(log, logtype::STACK, "%s\n", line.c_str());
 
     *sp += sizeof(word_t);
   }
@@ -325,44 +318,72 @@
   }
 }
 
-static void dump_map(log_t* log, const backtrace_map_t* map, bool fault_addr) {
-  _LOG(log, logtype::MAPS, "%s%" PRIPTR "-%" PRIPTR " %c%c%c  %7" PRIdPTR "%s\n",
-         (fault_addr? "--->" : "    "), map->start, map->end - 1,
-         (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-',
-         (map->flags & PROT_EXEC) ? 'x' : '-',
-         (map->end - map->start),
-         (map->name.length() > 0) ? ("  " + map->name).c_str() : "");
-}
-
-static void dump_all_maps(BacktraceMap* map, log_t* log, pid_t tid) {
-  bool has_fault_address = false;
+static void dump_all_maps(Backtrace* backtrace, BacktraceMap* map, log_t* log, pid_t tid) {
+  bool print_fault_address_marker = false;
   uintptr_t addr = 0;
   siginfo_t si;
   memset(&si, 0, sizeof(si));
   if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
-    _LOG(log, logtype::MAPS, "cannot get siginfo for %d: %s\n", tid, strerror(errno));
+    _LOG(log, logtype::ERROR, "cannot get siginfo for %d: %s\n", tid, strerror(errno));
   } else {
-    has_fault_address = signal_has_si_addr(si.si_signo);
+    print_fault_address_marker = signal_has_si_addr(si.si_signo);
     addr = reinterpret_cast<uintptr_t>(si.si_addr);
   }
 
-  _LOG(log, logtype::MAPS, "\nmemory map:%s\n", has_fault_address ? " (fault address prefixed with --->)" : "");
-
-  if (has_fault_address && (addr < map->begin()->start)) {
-    _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n", addr);
-  }
-
-  BacktraceMap::const_iterator prev = map->begin();
-  for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) {
-    if (addr >= (*prev).end && addr < (*it).start) {
-      _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n", addr);
+  _LOG(log, logtype::MAPS, "\n");
+  if (!print_fault_address_marker) {
+    _LOG(log, logtype::MAPS, "memory map:\n");
+  } else {
+    _LOG(log, logtype::MAPS, "memory map: (fault address prefixed with --->)\n");
+    if (map->begin() != map->end() && addr < map->begin()->start) {
+      _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n",
+           addr);
+      print_fault_address_marker = false;
     }
-    prev = it;
-    bool in_map = has_fault_address && (addr >= (*it).start) && (addr < (*it).end);
-    dump_map(log, &*it, in_map);
   }
-  if (has_fault_address && (addr >= (*prev).end)) {
-    _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n", addr);
+
+  std::string line;
+  for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) {
+    line = "    ";
+    if (print_fault_address_marker) {
+      if (addr < it->start) {
+        _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n",
+             addr);
+        print_fault_address_marker = false;
+      } else if (addr >= it->start && addr < it->end) {
+        line = "--->";
+        print_fault_address_marker = false;
+      }
+    }
+    line += android::base::StringPrintf("%" PRIPTR "-%" PRIPTR " ", it->start, it->end - 1);
+    if (it->flags & PROT_READ) {
+      line += 'r';
+    } else {
+      line += '-';
+    }
+    if (it->flags & PROT_WRITE) {
+      line += 'w';
+    } else {
+      line += '-';
+    }
+    if (it->flags & PROT_EXEC) {
+      line += 'x';
+    } else {
+      line += '-';
+    }
+    line += android::base::StringPrintf("  %8" PRIxPTR, it->end - it->start);
+    if (it->name.length() > 0) {
+      line += "  " + it->name;
+      std::string build_id;
+      if ((it->flags & PROT_READ) && elf_get_build_id(backtrace, it->start, &build_id)) {
+        line += " (BuildId: " + build_id + ")";
+      }
+    }
+    _LOG(log, logtype::MAPS, "%s\n", line.c_str());
+  }
+  if (print_fault_address_marker) {
+    _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n",
+        addr);
   }
 }
 
@@ -627,7 +648,7 @@
     dump_backtrace_and_stack(backtrace.get(), log);
   }
   dump_memory_and_code(log, tid);
-  dump_all_maps(map.get(), log, tid);
+  dump_all_maps(backtrace.get(), map.get(), log, tid);
 
   if (want_logs) {
     dump_logs(log, pid, 5);
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index aa5b14a..b9e957f 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -19,10 +19,11 @@
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/../mkbootimg \
   $(LOCAL_PATH)/../../extras/ext4_utils \
   $(LOCAL_PATH)/../../extras/f2fs_utils
-LOCAL_SRC_FILES := protocol.c engine.c bootimg.c fastboot.c util.c fs.c
+LOCAL_SRC_FILES := protocol.c engine.c bootimg_utils.cpp fastboot.cpp util.c fs.c
 LOCAL_MODULE := fastboot
 LOCAL_MODULE_TAGS := debug
-LOCAL_CFLAGS += -std=gnu99 -Werror
+LOCAL_CONLYFLAGS += -std=gnu99
+LOCAL_CFLAGS += -Wall -Wextra -Werror
 
 ifeq ($(HOST_OS),linux)
   LOCAL_SRC_FILES += usb_linux.c util_linux.c
@@ -52,9 +53,11 @@
 
 LOCAL_STATIC_LIBRARIES := \
     $(EXTRA_STATIC_LIBS) \
-    libzipfile \
+    libziparchive-host \
     libext4_utils_host \
     libsparse_host \
+    libutils \
+    liblog \
     libz
 
 ifneq ($(HOST_OS),windows)
diff --git a/fastboot/bootimg.c b/fastboot/bootimg_utils.cpp
similarity index 95%
rename from fastboot/bootimg.c
rename to fastboot/bootimg_utils.cpp
index 240784f..d8905a6 100644
--- a/fastboot/bootimg.c
+++ b/fastboot/bootimg_utils.cpp
@@ -26,12 +26,12 @@
  * SUCH DAMAGE.
  */
 
+#include "bootimg_utils.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <bootimg.h>
-
 void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline)
 {
     strcpy((char*) h->cmdline, cmdline);
@@ -47,7 +47,6 @@
     unsigned ramdisk_actual;
     unsigned second_actual;
     unsigned page_mask;
-    boot_img_hdr *hdr;
 
     page_mask = page_size - 1;
 
@@ -57,9 +56,8 @@
 
     *bootimg_size = page_size + kernel_actual + ramdisk_actual + second_actual;
 
-    hdr = calloc(*bootimg_size, 1);
-
-    if(hdr == 0) {
+    boot_img_hdr* hdr = reinterpret_cast<boot_img_hdr*>(calloc(*bootimg_size, 1));
+    if (hdr == 0) {
         return hdr;
     }
 
diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h
new file mode 100644
index 0000000..b1a86cd
--- /dev/null
+++ b/fastboot/bootimg_utils.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 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 _FASTBOOT_BOOTIMG_UTILS_H_
+#define _FASTBOOT_BOOTIMG_UTILS_H_
+
+#include <bootimg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
+boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
+                        void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
+                        void *second, unsigned second_size, unsigned second_offset,
+                        unsigned page_size, unsigned base, unsigned tags_offset,
+                        unsigned *bootimg_size);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.cpp
similarity index 90%
rename from fastboot/fastboot.c
rename to fastboot/fastboot.cpp
index fc544a6..6dc7d34 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.cpp
@@ -44,10 +44,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <bootimg.h>
 #include <sparse/sparse.h>
-#include <zipfile/zipfile.h>
+#include <ziparchive/zip_archive.h>
 
+#include "bootimg_utils.h"
 #include "fastboot.h"
 #include "fs.h"
 
@@ -59,14 +59,6 @@
 
 char cur_product[FB_RESPONSE_SZ + 1];
 
-void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
-
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
-                        void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
-                        void *second, unsigned second_size, unsigned second_offset,
-                        unsigned page_size, unsigned base, unsigned tags_offset,
-                        unsigned *bootimg_size);
-
 static usb_handle *usb = 0;
 static const char *serial = 0;
 static const char *product = 0;
@@ -106,12 +98,10 @@
     {"vendor.img", "vendor.sig", "vendor", true},
 };
 
-void get_my_path(char *path);
-
 char *find_item(const char *item, const char *product)
 {
     char *dir;
-    char *fn;
+    const char *fn;
     char path[PATH_MAX + 128];
 
     if(!strcmp(item,"boot")) {
@@ -234,7 +224,7 @@
 int list_devices_callback(usb_ifc_info *info)
 {
     if (match_fastboot_with_serial(info, NULL) == 0) {
-        char* serial = info->serial_number;
+        const char* serial = info->serial_number;
         if (!info->writable) {
             serial = "no permissions"; // like "adb devices"
         }
@@ -389,30 +379,26 @@
     return bdata;
 }
 
-void *unzip_file(zipfile_t zip, const char *name, unsigned *sz)
+static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, unsigned* sz)
 {
-    void *data;
-    zipentry_t entry;
-    unsigned datasz;
-
-    entry = lookup_zipentry(zip, name);
-    if (entry == NULL) {
-        fprintf(stderr, "archive does not contain '%s'\n", name);
+    ZipEntryName zip_entry_name(entry_name);
+    ZipEntry zip_entry;
+    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
+        fprintf(stderr, "archive does not contain '%s'\n", entry_name);
         return 0;
     }
 
-    *sz = get_zipentry_size(entry);
+    *sz = zip_entry.uncompressed_length;
 
-    datasz = *sz * 1.001;
-    data = malloc(datasz);
-
-    if(data == 0) {
-        fprintf(stderr, "failed to allocate %d bytes\n", *sz);
+    uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
+    if (data == NULL) {
+        fprintf(stderr, "failed to allocate %u bytes for '%s'\n", *sz, entry_name);
         return 0;
     }
 
-    if (decompress_zipentry(entry, data, datasz)) {
-        fprintf(stderr, "failed to unzip '%s' from archive\n", name);
+    int error = ExtractToMemory(zip, &zip_entry, data, zip_entry.uncompressed_length);
+    if (error != 0) {
+        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
         free(data);
         return 0;
     }
@@ -420,27 +406,28 @@
     return data;
 }
 
-static int unzip_to_file(zipfile_t zip, char *name)
-{
-    int fd;
-    char *data;
-    unsigned sz;
-
-    fd = fileno(tmpfile());
-    if (fd < 0) {
+static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
+    FILE* fp = tmpfile();
+    if (fp == NULL) {
+        fprintf(stderr, "failed to create temporary file for '%s': %s\n",
+                entry_name, strerror(errno));
         return -1;
     }
 
-    data = unzip_file(zip, name, &sz);
-    if (data == 0) {
+    ZipEntryName zip_entry_name(entry_name);
+    ZipEntry zip_entry;
+    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
+        fprintf(stderr, "archive does not contain '%s'\n", entry_name);
         return -1;
     }
 
-    if (write(fd, data, sz) != (ssize_t)sz) {
-        fd = -1;
+    int fd = fileno(fp);
+    int error = ExtractEntryToFile(zip, &zip_entry, fd);
+    if (error != 0) {
+        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
+        return -1;
     }
 
-    free(data);
     lseek(fd, 0, SEEK_SET);
     return fd;
 }
@@ -461,7 +448,6 @@
 static int setup_requirement_line(char *name)
 {
     char *val[MAX_OPTIONS];
-    const char **out;
     char *prod = NULL;
     unsigned n, count;
     char *x;
@@ -501,10 +487,11 @@
     name = strip(name);
     if (name == 0) return -1;
 
-        /* work around an unfortunate name mismatch */
-    if (!strcmp(name,"board")) name = "product";
+    const char* var = name;
+    // Work around an unfortunate name mismatch.
+    if (!strcmp(name,"board")) var = "product";
 
-    out = malloc(sizeof(char*) * count);
+    const char** out = reinterpret_cast<const char**>(malloc(sizeof(char*) * count));
     if (out == 0) return -1;
 
     for(n = 0; n < count; n++) {
@@ -518,7 +505,7 @@
         }
     }
 
-    fb_queue_require(prod, name, invert, n, out);
+    fb_queue_require(prod, var, invert, n, out);
     return 0;
 }
 
@@ -551,21 +538,17 @@
 
 static struct sparse_file **load_sparse_files(int fd, int max_size)
 {
-    struct sparse_file *s;
-    int files;
-    struct sparse_file **out_s;
-
-    s = sparse_file_import_auto(fd, false);
+    struct sparse_file* s = sparse_file_import_auto(fd, false);
     if (!s) {
         die("cannot sparse read file\n");
     }
 
-    files = sparse_file_resparse(s, max_size, NULL, 0);
+    int files = sparse_file_resparse(s, max_size, NULL, 0);
     if (files < 0) {
         die("Failed to resparse\n");
     }
 
-    out_s = calloc(sizeof(struct sparse_file *), files + 1);
+    sparse_file** out_s = reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file *), files + 1));
     if (!out_s) {
         die("Failed to allocate sparse file array\n");
     }
@@ -682,11 +665,11 @@
 
 static void flash_buf(const char *pname, struct fastboot_buffer *buf)
 {
-    struct sparse_file **s;
+    sparse_file** s;
 
     switch (buf->type) {
         case FB_BUFFER_SPARSE:
-            s = buf->data;
+            s = reinterpret_cast<sparse_file**>(buf->data);
             while (*s) {
                 int64_t sz64 = sparse_file_len(*s, true, false);
                 fb_queue_flash_sparse(pname, *s++, sz64);
@@ -710,63 +693,44 @@
     flash_buf(pname, &buf);
 }
 
-void do_update_signature(zipfile_t zip, char *fn)
+void do_update_signature(ZipArchiveHandle zip, char *fn)
 {
-    void *data;
     unsigned sz;
-    data = unzip_file(zip, fn, &sz);
+    void* data = unzip_file(zip, fn, &sz);
     if (data == 0) return;
     fb_queue_download("signature", data, sz);
     fb_queue_command("signature", "installing signature");
 }
 
-void do_update(usb_handle *usb, char *fn, int erase_first)
+void do_update(usb_handle *usb, const char *filename, int erase_first)
 {
-    void *zdata;
-    unsigned zsize;
-    void *data;
-    unsigned sz;
-    zipfile_t zip;
-    int fd;
-    int rc;
-    struct fastboot_buffer buf;
-    size_t i;
-
     queue_info_dump();
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
 
-    zdata = load_file(fn, &zsize);
-    if (zdata == 0) die("failed to load '%s': %s", fn, strerror(errno));
-
-    zip = init_zipfile(zdata, zsize);
-    if(zip == 0) die("failed to access zipdata in '%s'");
-
-    data = unzip_file(zip, "android-info.txt", &sz);
-    if (data == 0) {
-        char *tmp;
-            /* fallback for older zipfiles */
-        data = unzip_file(zip, "android-product.txt", &sz);
-        if ((data == 0) || (sz < 1)) {
-            die("update package has no android-info.txt or android-product.txt");
-        }
-        tmp = malloc(sz + 128);
-        if (tmp == 0) die("out of memory");
-        sprintf(tmp,"board=%sversion-baseband=0.66.04.19\n",(char*)data);
-        data = tmp;
-        sz = strlen(tmp);
+    ZipArchiveHandle zip;
+    int error = OpenArchive(filename, &zip);
+    if (error != 0) {
+        die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
     }
 
-    setup_requirements(data, sz);
+    unsigned sz;
+    void* data = unzip_file(zip, "android-info.txt", &sz);
+    if (data == 0) {
+        die("update package '%s' has no android-info.txt", filename);
+    }
 
-    for (i = 0; i < ARRAY_SIZE(images); i++) {
-        fd = unzip_to_file(zip, images[i].img_name);
+    setup_requirements(reinterpret_cast<char*>(data), sz);
+
+    for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
+        int fd = unzip_to_file(zip, images[i].img_name);
         if (fd < 0) {
             if (images[i].is_optional)
                 continue;
             die("update package missing %s", images[i].img_name);
         }
-        rc = load_buf_fd(usb, fd, &buf);
+        fastboot_buffer buf;
+        int rc = load_buf_fd(usb, fd, &buf);
         if (rc) die("cannot load %s from flash", images[i].img_name);
         do_update_signature(zip, images[i].sig_name);
         if (erase_first && needs_erase(images[i].part_name)) {
@@ -778,6 +742,8 @@
          * program exits.
          */
     }
+
+    CloseArchive(zip);
 }
 
 void do_send_signature(char *fn)
@@ -800,24 +766,22 @@
 
 void do_flashall(usb_handle *usb, int erase_first)
 {
-    char *fname;
-    void *data;
-    unsigned sz;
-    struct fastboot_buffer buf;
-    size_t i;
-
     queue_info_dump();
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
 
-    fname = find_item("info", product);
+    char* fname = find_item("info", product);
     if (fname == 0) die("cannot find android-info.txt");
-    data = load_file(fname, &sz);
-    if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
-    setup_requirements(data, sz);
 
-    for (i = 0; i < ARRAY_SIZE(images); i++) {
+    unsigned sz;
+    void* data = load_file(fname, &sz);
+    if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
+
+    setup_requirements(reinterpret_cast<char*>(data), sz);
+
+    for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
         fname = find_item(images[i].part_name, product);
+        fastboot_buffer buf;
         if (load_buf(usb, fname, &buf)) {
             if (images[i].is_optional)
                 continue;
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index fc5d4f4..1786e49 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -31,6 +31,10 @@
 
 #include "usb.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 struct sparse_file;
 
 /* protocol.c - fastboot protocol */
@@ -67,7 +71,13 @@
 char *mkmsg(const char *fmt, ...);
 void die(const char *fmt, ...);
 
+void get_my_path(char *path);
+
 /* Current product */
 extern char cur_product[FB_RESPONSE_SZ + 1];
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/fastboot/fs.h b/fastboot/fs.h
index 8444081..307772b 100644
--- a/fastboot/fs.h
+++ b/fastboot/fs.h
@@ -3,10 +3,18 @@
 
 #include <stdint.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 struct fs_generator;
 
 const struct fs_generator* fs_get_generator(const char *fs_type);
 int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize);
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
 
diff --git a/fastboot/protocol.c b/fastboot/protocol.c
index 10a84c1..5b97600 100644
--- a/fastboot/protocol.c
+++ b/fastboot/protocol.c
@@ -305,7 +305,10 @@
         return -1;
     }
 
-    fb_download_data_sparse_flush(usb);
+    r = fb_download_data_sparse_flush(usb);
+    if (r < 0) {
+        return -1;
+    }
 
     return _command_end(usb);
 }
diff --git a/fastboot/usb.h b/fastboot/usb.h
index 17cf0a9..c7b748e 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -29,6 +29,10 @@
 #ifndef _USB_H_
 #define _USB_H_
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 typedef struct usb_handle usb_handle;
 
 typedef struct usb_ifc_info usb_ifc_info;
@@ -64,4 +68,8 @@
 int usb_write(usb_handle *h, const void *_data, int len);
 int usb_wait_for_disconnect(usb_handle *h);
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h
index e2d718b..8c39acb 100644
--- a/include/backtrace/Backtrace.h
+++ b/include/backtrace/Backtrace.h
@@ -84,6 +84,12 @@
   // Read the data at a specific address.
   virtual bool ReadWord(uintptr_t ptr, word_t* out_value) = 0;
 
+  // Read arbitrary data from a specific address. If a read request would
+  // span from one map to another, this call only reads up until the end
+  // of the current map.
+  // Returns the total number of bytes actually read.
+  virtual size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) = 0;
+
   // Create a string representing the formatted line of backtrace information
   // for a single frame.
   virtual std::string FormatFrameData(size_t frame_num);
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 101cacd..a3d11a7 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -230,21 +230,14 @@
 static const struct fs_path_config android_files[] = {
     { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.rc" },
     { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.sh" },
-    { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.trout.rc" },
     { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },
     { 00550, AID_DHCP,      AID_SHELL,     0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
-    { 00444, AID_RADIO,     AID_AUDIO,     0, "system/etc/AudioPara4.csv" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
     { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },
     { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
     { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },
     { 00644, AID_APP,       AID_APP,       0, "data/data/*" },
-    { 00755, AID_ROOT,      AID_ROOT,      0, "system/bin/ping" },
-
-    /* the following file is INTENTIONALLY set-gid and not set-uid.
-     * Do not change. */
-    { 02750, AID_ROOT,      AID_INET,      0, "system/bin/netcfg" },
 
     /* the following five files are INTENTIONALLY set-uid, but they
      * are NOT included on user builds. */
diff --git a/init/Android.mk b/init/Android.mk
index ec2861b..5b8094f 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -27,6 +27,7 @@
     parser.cpp \
     util.cpp \
 
+LOCAL_STATIC_LIBRARIES := libbase
 LOCAL_MODULE := libinit
 include $(BUILD_STATIC_LIBRARY)
 
@@ -55,7 +56,7 @@
     libfs_mgr \
     liblogwrap \
     libcutils \
-    libutils \
+    libbase \
     liblog \
     libc \
     libselinux \
@@ -80,7 +81,7 @@
 
 LOCAL_SHARED_LIBRARIES += \
     libcutils \
-    libutils \
+    libbase \
 
 LOCAL_STATIC_LIBRARIES := libinit
 include $(BUILD_NATIVE_TEST)
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index cc31920..530eba8 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -32,7 +32,7 @@
 
 #include <string>
 
-#include <utils/file.h>
+#include <base/file.h>
 
 #define LOG_ROOT        "/data/bootchart"
 #define LOG_STAT        LOG_ROOT"/proc_stat.log"
@@ -59,7 +59,7 @@
 
 static long long get_uptime_jiffies() {
     std::string uptime;
-    if (!android::ReadFileToString("/proc/uptime", &uptime)) {
+    if (!android::base::ReadFileToString("/proc/uptime", &uptime)) {
         return 0;
     }
     return 100LL * strtod(uptime.c_str(), NULL);
@@ -82,7 +82,7 @@
     }
 
     std::string kernel_cmdline;
-    android::ReadFileToString("/proc/cmdline", &kernel_cmdline);
+    android::base::ReadFileToString("/proc/cmdline", &kernel_cmdline);
 
     FILE* out = fopen(LOG_HEADER, "we");
     if (out == NULL) {
@@ -106,7 +106,7 @@
     do_log_uptime(log);
 
     std::string content;
-    if (android::ReadFileToString(procfile, &content)) {
+    if (android::base::ReadFileToString(procfile, &content)) {
         fprintf(log, "%s\n", content.c_str());
     }
 }
@@ -127,13 +127,13 @@
             // name from /proc/<pid>/cmdline.
             snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid);
             std::string cmdline;
-            android::ReadFileToString(filename, &cmdline);
+            android::base::ReadFileToString(filename, &cmdline);
             const char* full_name = cmdline.c_str(); // So we stop at the first NUL.
 
             // Read process stat line.
             snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
             std::string stat;
-            if (android::ReadFileToString(filename, &stat)) {
+            if (android::base::ReadFileToString(filename, &stat)) {
                 if (!cmdline.empty()) {
                     // Substitute the process name with its real name.
                     size_t open = stat.find('(');
@@ -155,7 +155,7 @@
     int timeout = 0;
 
     std::string start;
-    android::ReadFileToString(LOG_STARTFILE, &start);
+    android::base::ReadFileToString(LOG_STARTFILE, &start);
     if (!start.empty()) {
         timeout = atoi(start.c_str());
     } else {
@@ -164,7 +164,7 @@
         // timeout. this is useful when using -wipe-data since the /data
         // partition is fresh.
         std::string cmdline;
-        android::ReadFileToString("/proc/cmdline", &cmdline);
+        android::base::ReadFileToString("/proc/cmdline", &cmdline);
 #define KERNEL_OPTION  "androidboot.bootchart="
         if (strstr(cmdline.c_str(), KERNEL_OPTION) != NULL) {
             timeout = atoi(cmdline.c_str() + sizeof(KERNEL_OPTION) - 1);
@@ -226,7 +226,7 @@
 
     // Stop if /data/bootchart/stop contains 1.
     std::string stop;
-    if (android::ReadFileToString(LOG_STOPFILE, &stop) && stop == "1") {
+    if (android::base::ReadFileToString(LOG_STOPFILE, &stop) && stop == "1") {
         return -1;
     }
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 5d1ad29..fb1aa7c 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -104,18 +104,6 @@
     }
 }
 
-int do_chdir(int nargs, char **args)
-{
-    chdir(args[1]);
-    return 0;
-}
-
-int do_chroot(int nargs, char **args)
-{
-    chroot(args[1]);
-    return 0;
-}
-
 int do_class_start(int nargs, char **args)
 {
         /* Starting a class does not start services
diff --git a/init/init.cpp b/init/init.cpp
index 1a4bf0b..3418d65 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
+#include <paths.h>
 #include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -676,7 +677,6 @@
     if (urandom_fd != -1) {
         close(urandom_fd);
     }
-    memset(buf, 0, sizeof(buf));
     return result;
 }
 
@@ -978,6 +978,8 @@
     // Clear the umask.
     umask(0);
 
+    add_environment("PATH", _PATH_DEFPATH);
+
     // Get the basic filesystem setup we need put together in the initramdisk
     // on / and then we'll let the rc file figure out the rest.
     mkdir("/dev", 0755);
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 7f8e302..f3d34b2 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -121,8 +121,6 @@
     case 'c':
         if (!strcmp(s, "opy")) return K_copy;
         if (!strcmp(s, "apability")) return K_capability;
-        if (!strcmp(s, "hdir")) return K_chdir;
-        if (!strcmp(s, "hroot")) return K_chroot;
         if (!strcmp(s, "lass")) return K_class;
         if (!strcmp(s, "lass_start")) return K_class_start;
         if (!strcmp(s, "lass_stop")) return K_class_stop;
diff --git a/init/keywords.h b/init/keywords.h
index 0b37e27..c8327c3 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -1,7 +1,5 @@
 #ifndef KEYWORD
 int do_bootchart_init(int nargs, char **args);
-int do_chroot(int nargs, char **args);
-int do_chdir(int nargs, char **args);
 int do_class_start(int nargs, char **args);
 int do_class_stop(int nargs, char **args);
 int do_class_reset(int nargs, char **args);
@@ -46,8 +44,6 @@
     K_UNKNOWN,
 #endif
     KEYWORD(capability,  OPTION,  0, 0)
-    KEYWORD(chdir,       COMMAND, 1, do_chdir)
-    KEYWORD(chroot,      COMMAND, 1, do_chroot)
     KEYWORD(class,       OPTION,  0, 0)
     KEYWORD(class_start, COMMAND, 1, do_class_start)
     KEYWORD(class_stop,  COMMAND, 1, do_class_stop)
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 05c03d6..ddb8050 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -30,8 +30,6 @@
 #include <cutils/sockets.h>
 #include <cutils/multiuser.h>
 
-#include <utils/file.h>
-
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
diff --git a/init/readme.txt b/init/readme.txt
index d2933b9..7443330 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -164,18 +164,12 @@
 hostname <name>
    Set the host name.
 
-chdir <directory>
-   Change working directory.
-
 chmod <octal-mode> <path>
    Change file access permissions.
 
 chown <owner> <group> <path>
    Change file owner and group.
 
-chroot <directory>
-  Change process root directory.
-
 class_start <serviceclass>
    Start all services of the specified class if they are
    not already running.
@@ -205,13 +199,16 @@
 mkdir <path> [mode] [owner] [group]
    Create a directory at <path>, optionally with the given mode, owner, and
    group. If not provided, the directory is created with permissions 755 and
-   owned by the root user and root group.
+   owned by the root user and root group. If provided, the mode, owner and group
+   will be updated if the directory exists already.
 
-mount <type> <device> <dir> [ <mountoption> ]*
+mount <type> <device> <dir> [ <flag> ]* [<options>]
    Attempt to mount the named device at the directory <dir>
    <device> may be of the form mtd@name to specify a mtd block
    device by name.
-   <mountoption>s include "ro", "rw", "remount", "noatime", ...
+   <flag>s include "ro", "rw", "remount", "noatime", ...
+   <options> include "barrier=1", "noauto_da_alloc", "discard", ... as
+   a comma separated string, eg: barrier=1,noauto_da_alloc
 
 restorecon <path> [ <path> ]*
    Restore the file named by <path> to the security context specified
diff --git a/init/util.cpp b/init/util.cpp
index 0726053..8b238d4 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -32,11 +32,11 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include <base/file.h>
+
 /* for ANDROID_SOCKET_* */
 #include <cutils/sockets.h>
 
-#include <utils/file.h>
-
 #include <private/android_filesystem_config.h>
 
 #include "init.h"
@@ -168,7 +168,7 @@
         return false;
     }
 
-    bool okay = android::ReadFdToString(fd, content);
+    bool okay = android::base::ReadFdToString(fd, content);
     TEMP_FAILURE_RETRY(close(fd));
     if (okay) {
         content->append("\n", 1);
@@ -181,7 +181,7 @@
     if (fd == -1) {
         return -errno;
     }
-    int result = android::WriteStringToFd(content, fd) ? 0 : -errno;
+    int result = android::base::WriteStringToFd(content, fd) ? 0 : -errno;
     TEMP_FAILURE_RETRY(close(fd));
     return result;
 }
diff --git a/libbacktrace/BacktraceImpl.cpp b/libbacktrace/BacktraceImpl.cpp
index fb8a725..4650b6a 100644
--- a/libbacktrace/BacktraceImpl.cpp
+++ b/libbacktrace/BacktraceImpl.cpp
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/param.h>
 #include <sys/ptrace.h>
 #include <sys/types.h>
 #include <ucontext.h>
@@ -159,6 +160,17 @@
   }
 }
 
+size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
+  backtrace_map_t map;
+  FillInMap(addr, &map);
+  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+    return 0;
+  }
+  bytes = MIN(map.end - addr, bytes);
+  memcpy(buffer, reinterpret_cast<uint8_t*>(addr), bytes);
+  return bytes;
+}
+
 //-------------------------------------------------------------------------
 // BacktracePtrace functions.
 //-------------------------------------------------------------------------
@@ -171,25 +183,88 @@
 BacktracePtrace::~BacktracePtrace() {
 }
 
-bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
-  if (!VerifyReadWordArgs(ptr, out_value)) {
+#if !defined(__APPLE__)
+static bool PtraceRead(pid_t tid, uintptr_t addr, word_t* out_value) {
+  // ptrace() returns -1 and sets errno when the operation fails.
+  // To disambiguate -1 from a valid result, we clear errno beforehand.
+  errno = 0;
+  *out_value = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr), NULL);
+  if (*out_value == static_cast<word_t>(-1) && errno) {
+    BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
+              reinterpret_cast<void*>(addr), tid, strerror(errno));
     return false;
   }
+  return true;
+}
+#endif
 
+bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
 #if defined(__APPLE__)
   BACK_LOGW("MacOS does not support reading from another pid.");
   return false;
 #else
-  // ptrace() returns -1 and sets errno when the operation fails.
-  // To disambiguate -1 from a valid result, we clear errno beforehand.
-  errno = 0;
-  *out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL);
-  if (*out_value == static_cast<word_t>(-1) && errno) {
-    BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
-              reinterpret_cast<void*>(ptr), Tid(), strerror(errno));
+  if (!VerifyReadWordArgs(ptr, out_value)) {
     return false;
   }
-  return true;
+
+  backtrace_map_t map;
+  FillInMap(ptr, &map);
+  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+    return false;
+  }
+
+  return PtraceRead(Tid(), ptr, out_value);
+#endif
+}
+
+size_t BacktracePtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
+#if defined(__APPLE__)
+  BACK_LOGW("MacOS does not support reading from another pid.");
+  return 0;
+#else
+  backtrace_map_t map;
+  FillInMap(addr, &map);
+  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+    return 0;
+  }
+
+  bytes = MIN(map.end - addr, bytes);
+  size_t bytes_read = 0;
+  word_t data_word;
+  size_t align_bytes = addr & (sizeof(word_t) - 1);
+  if (align_bytes != 0) {
+    if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) {
+      return 0;
+    }
+    align_bytes = sizeof(word_t) - align_bytes;
+    memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + sizeof(word_t) - align_bytes,
+           align_bytes);
+    addr += align_bytes;
+    buffer += align_bytes;
+    bytes -= align_bytes;
+    bytes_read += align_bytes;
+  }
+
+  size_t num_words = bytes / sizeof(word_t);
+  for (size_t i = 0; i < num_words; i++) {
+    if (!PtraceRead(Tid(), addr, &data_word)) {
+      return bytes_read;
+    }
+    memcpy(buffer, &data_word, sizeof(word_t));
+    buffer += sizeof(word_t);
+    addr += sizeof(word_t);
+    bytes_read += sizeof(word_t);
+  }
+
+  size_t left_over = bytes & (sizeof(word_t) - 1);
+  if (left_over) {
+    if (!PtraceRead(Tid(), addr, &data_word)) {
+      return bytes_read;
+    }
+    memcpy(buffer, &data_word, left_over);
+    bytes_read += left_over;
+  }
+  return bytes_read;
 #endif
 }
 
diff --git a/libbacktrace/BacktraceImpl.h b/libbacktrace/BacktraceImpl.h
index cd61bdf..18c3cb5 100755
--- a/libbacktrace/BacktraceImpl.h
+++ b/libbacktrace/BacktraceImpl.h
@@ -56,6 +56,8 @@
   BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map);
   virtual ~BacktraceCurrent();
 
+  size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes);
+
   bool ReadWord(uintptr_t ptr, word_t* out_value);
 };
 
@@ -64,6 +66,8 @@
   BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map);
   virtual ~BacktracePtrace();
 
+  size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes);
+
   bool ReadWord(uintptr_t ptr, word_t* out_value);
 };
 
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 76aabd1..b1e34bd 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -31,7 +31,6 @@
 
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
-#include <UniquePtr.h>
 
 // For the THREAD_SIGNAL definition.
 #include "BacktraceThread.h"
@@ -40,6 +39,7 @@
 #include <gtest/gtest.h>
 
 #include <algorithm>
+#include <memory>
 #include <vector>
 
 #include "thread_utils.h"
@@ -60,6 +60,7 @@
   pid_t tid;
   int32_t state;
   pthread_t threadId;
+  void* data;
 };
 
 struct dump_thread_t {
@@ -142,9 +143,9 @@
 }
 
 void VerifyLevelBacktrace(void*) {
-  UniquePtr<Backtrace> backtrace(
+  std::unique_ptr<Backtrace> backtrace(
       Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
-  ASSERT_TRUE(backtrace.get() != NULL);
+  ASSERT_TRUE(backtrace.get() != nullptr);
   ASSERT_TRUE(backtrace->Unwind(0));
 
   VerifyLevelDump(backtrace.get());
@@ -162,9 +163,9 @@
 }
 
 void VerifyMaxBacktrace(void*) {
-  UniquePtr<Backtrace> backtrace(
+  std::unique_ptr<Backtrace> backtrace(
       Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
-  ASSERT_TRUE(backtrace.get() != NULL);
+  ASSERT_TRUE(backtrace.get() != nullptr);
   ASSERT_TRUE(backtrace->Unwind(0));
 
   VerifyMaxDump(backtrace.get());
@@ -180,8 +181,8 @@
 }
 
 void VerifyThreadTest(pid_t tid, void (*VerifyFunc)(Backtrace*)) {
-  UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
-  ASSERT_TRUE(backtrace.get() != NULL);
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
+  ASSERT_TRUE(backtrace.get() != nullptr);
   ASSERT_TRUE(backtrace->Unwind(0));
 
   VerifyFunc(backtrace.get());
@@ -198,7 +199,7 @@
 }
 
 TEST(libbacktrace, local_trace) {
-  ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, NULL), 0);
+  ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
 }
 
 void VerifyIgnoreFrames(
@@ -208,7 +209,7 @@
   EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2);
 
   // Check all of the frames are the same > the current frame.
-  bool check = (cur_proc == NULL);
+  bool check = (cur_proc == nullptr);
   for (size_t i = 0; i < bt_ign2->NumFrames(); i++) {
     if (check) {
       EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_ign1->GetFrame(i+1)->pc);
@@ -226,30 +227,30 @@
 }
 
 void VerifyLevelIgnoreFrames(void*) {
-  UniquePtr<Backtrace> all(
+  std::unique_ptr<Backtrace> all(
       Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
-  ASSERT_TRUE(all.get() != NULL);
+  ASSERT_TRUE(all.get() != nullptr);
   ASSERT_TRUE(all->Unwind(0));
 
-  UniquePtr<Backtrace> ign1(
+  std::unique_ptr<Backtrace> ign1(
       Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
-  ASSERT_TRUE(ign1.get() != NULL);
+  ASSERT_TRUE(ign1.get() != nullptr);
   ASSERT_TRUE(ign1->Unwind(1));
 
-  UniquePtr<Backtrace> ign2(
+  std::unique_ptr<Backtrace> ign2(
       Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
-  ASSERT_TRUE(ign2.get() != NULL);
+  ASSERT_TRUE(ign2.get() != nullptr);
   ASSERT_TRUE(ign2->Unwind(2));
 
   VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), "VerifyLevelIgnoreFrames");
 }
 
 TEST(libbacktrace, local_trace_ignore_frames) {
-  ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelIgnoreFrames, NULL), 0);
+  ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelIgnoreFrames, nullptr), 0);
 }
 
 TEST(libbacktrace, local_max_trace) {
-  ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, NULL), 0);
+  ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, nullptr), 0);
 }
 
 void VerifyProcTest(pid_t pid, pid_t tid, bool share_map,
@@ -269,13 +270,13 @@
       // Wait for the process to get to a stopping point.
       WaitForStop(ptrace_tid);
 
-      UniquePtr<BacktraceMap> map;
+      std::unique_ptr<BacktraceMap> map;
       if (share_map) {
         map.reset(BacktraceMap::Create(pid));
       }
-      UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
+      std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
       ASSERT_TRUE(backtrace->Unwind(0));
-      ASSERT_TRUE(backtrace.get() != NULL);
+      ASSERT_TRUE(backtrace.get() != nullptr);
       if (ReadyFunc(backtrace.get())) {
         VerifyFunc(backtrace.get());
         verified = true;
@@ -291,7 +292,7 @@
 TEST(libbacktrace, ptrace_trace) {
   pid_t pid;
   if ((pid = fork()) == 0) {
-    ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+    ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
     _exit(1);
   }
   VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyLevelDump);
@@ -304,7 +305,7 @@
 TEST(libbacktrace, ptrace_trace_shared_map) {
   pid_t pid;
   if ((pid = fork()) == 0) {
-    ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+    ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
     _exit(1);
   }
 
@@ -318,7 +319,7 @@
 TEST(libbacktrace, ptrace_max_trace) {
   pid_t pid;
   if ((pid = fork()) == 0) {
-    ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, NULL, NULL), 0);
+    ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, nullptr, nullptr), 0);
     _exit(1);
   }
   VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyMaxBacktrace, VerifyMaxDump);
@@ -329,21 +330,21 @@
 }
 
 void VerifyProcessIgnoreFrames(Backtrace* bt_all) {
-  UniquePtr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
-  ASSERT_TRUE(ign1.get() != NULL);
+  std::unique_ptr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
+  ASSERT_TRUE(ign1.get() != nullptr);
   ASSERT_TRUE(ign1->Unwind(1));
 
-  UniquePtr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
-  ASSERT_TRUE(ign2.get() != NULL);
+  std::unique_ptr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
+  ASSERT_TRUE(ign2.get() != nullptr);
   ASSERT_TRUE(ign2->Unwind(2));
 
-  VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), NULL);
+  VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), nullptr);
 }
 
 TEST(libbacktrace, ptrace_ignore_frames) {
   pid_t pid;
   if ((pid = fork()) == 0) {
-    ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+    ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
     _exit(1);
   }
   VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyProcessIgnoreFrames);
@@ -355,8 +356,8 @@
 
 // Create a process with multiple threads and dump all of the threads.
 void* PtraceThreadLevelRun(void*) {
-  EXPECT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
-  return NULL;
+  EXPECT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
+  return nullptr;
 }
 
 void GetThreads(pid_t pid, std::vector<pid_t>* threads) {
@@ -365,9 +366,9 @@
   snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
 
   DIR* tasks_dir = opendir(task_path);
-  ASSERT_TRUE(tasks_dir != NULL);
+  ASSERT_TRUE(tasks_dir != nullptr);
   struct dirent* entry;
-  while ((entry = readdir(tasks_dir)) != NULL) {
+  while ((entry = readdir(tasks_dir)) != nullptr) {
     char* end;
     pid_t tid = strtoul(entry->d_name, &end, 10);
     if (*end == '\0') {
@@ -386,9 +387,9 @@
       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
       pthread_t thread;
-      ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, NULL) == 0);
+      ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, nullptr) == 0);
     }
-    ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+    ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
     _exit(1);
   }
 
@@ -420,27 +421,27 @@
 }
 
 void VerifyLevelThread(void*) {
-  UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
-  ASSERT_TRUE(backtrace.get() != NULL);
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
+  ASSERT_TRUE(backtrace.get() != nullptr);
   ASSERT_TRUE(backtrace->Unwind(0));
 
   VerifyLevelDump(backtrace.get());
 }
 
 TEST(libbacktrace, thread_current_level) {
-  ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, NULL), 0);
+  ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, nullptr), 0);
 }
 
 void VerifyMaxThread(void*) {
-  UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
-  ASSERT_TRUE(backtrace.get() != NULL);
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
+  ASSERT_TRUE(backtrace.get() != nullptr);
   ASSERT_TRUE(backtrace->Unwind(0));
 
   VerifyMaxDump(backtrace.get());
 }
 
 TEST(libbacktrace, thread_current_max) {
-  ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, NULL), 0);
+  ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, nullptr), 0);
 }
 
 void* ThreadLevelRun(void* data) {
@@ -448,7 +449,7 @@
 
   thread->tid = gettid();
   EXPECT_NE(test_level_one(1, 2, 3, 4, ThreadSetState, data), 0);
-  return NULL;
+  return nullptr;
 }
 
 TEST(libbacktrace, thread_level_trace) {
@@ -456,7 +457,7 @@
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
-  thread_t thread_data = { 0, 0, 0 };
+  thread_t thread_data = { 0, 0, 0, nullptr };
   pthread_t thread;
   ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0);
 
@@ -471,10 +472,10 @@
 
   // Save the current signal action and make sure it is restored afterwards.
   struct sigaction cur_action;
-  ASSERT_TRUE(sigaction(THREAD_SIGNAL, NULL, &cur_action) == 0);
+  ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &cur_action) == 0);
 
-  UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
-  ASSERT_TRUE(backtrace.get() != NULL);
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
+  ASSERT_TRUE(backtrace.get() != nullptr);
   ASSERT_TRUE(backtrace->Unwind(0));
 
   VerifyLevelDump(backtrace.get());
@@ -484,7 +485,7 @@
 
   // Verify that the old action was restored.
   struct sigaction new_action;
-  ASSERT_TRUE(sigaction(THREAD_SIGNAL, NULL, &new_action) == 0);
+  ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &new_action) == 0);
   EXPECT_EQ(cur_action.sa_sigaction, new_action.sa_sigaction);
   // The SA_RESTORER flag gets set behind our back, so a direct comparison
   // doesn't work unless we mask the value off. Mips doesn't have this
@@ -501,26 +502,26 @@
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
-  thread_t thread_data = { 0, 0, 0 };
+  thread_t thread_data = { 0, 0, 0, nullptr };
   pthread_t thread;
   ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0);
 
   // Wait up to 2 seconds for the tid to be set.
   ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
 
-  UniquePtr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid));
-  ASSERT_TRUE(all.get() != NULL);
+  std::unique_ptr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid));
+  ASSERT_TRUE(all.get() != nullptr);
   ASSERT_TRUE(all->Unwind(0));
 
-  UniquePtr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid));
-  ASSERT_TRUE(ign1.get() != NULL);
+  std::unique_ptr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid));
+  ASSERT_TRUE(ign1.get() != nullptr);
   ASSERT_TRUE(ign1->Unwind(1));
 
-  UniquePtr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid));
-  ASSERT_TRUE(ign2.get() != NULL);
+  std::unique_ptr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid));
+  ASSERT_TRUE(ign2.get() != nullptr);
   ASSERT_TRUE(ign2->Unwind(2));
 
-  VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), NULL);
+  VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), nullptr);
 
   // Tell the thread to exit its infinite loop.
   android_atomic_acquire_store(0, &thread_data.state);
@@ -531,7 +532,7 @@
 
   thread->tid = gettid();
   EXPECT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, ThreadSetState, data), 0);
-  return NULL;
+  return nullptr;
 }
 
 TEST(libbacktrace, thread_max_trace) {
@@ -539,15 +540,15 @@
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
-  thread_t thread_data = { 0, 0, 0 };
+  thread_t thread_data = { 0, 0, 0, nullptr };
   pthread_t thread;
   ASSERT_TRUE(pthread_create(&thread, &attr, ThreadMaxRun, &thread_data) == 0);
 
   // Wait for the tid to be set.
   ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
 
-  UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
-  ASSERT_TRUE(backtrace.get() != NULL);
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
+  ASSERT_TRUE(backtrace.get() != nullptr);
   ASSERT_TRUE(backtrace->Unwind(0));
 
   VerifyMaxDump(backtrace.get());
@@ -570,7 +571,7 @@
 
   android_atomic_acquire_store(1, &dump->done);
 
-  return NULL;
+  return nullptr;
 }
 
 TEST(libbacktrace, thread_multiple_dump) {
@@ -614,11 +615,11 @@
     // Tell the runner thread to exit its infinite loop.
     android_atomic_acquire_store(0, &runners[i].state);
 
-    ASSERT_TRUE(dumpers[i].backtrace != NULL);
+    ASSERT_TRUE(dumpers[i].backtrace != nullptr);
     VerifyMaxDump(dumpers[i].backtrace);
 
     delete dumpers[i].backtrace;
-    dumpers[i].backtrace = NULL;
+    dumpers[i].backtrace = nullptr;
   }
 }
 
@@ -654,11 +655,11 @@
   for (size_t i = 0; i < NUM_THREADS; i++) {
     ASSERT_TRUE(WaitForNonZero(&dumpers[i].done, 30));
 
-    ASSERT_TRUE(dumpers[i].backtrace != NULL);
+    ASSERT_TRUE(dumpers[i].backtrace != nullptr);
     VerifyMaxDump(dumpers[i].backtrace);
 
     delete dumpers[i].backtrace;
-    dumpers[i].backtrace = NULL;
+    dumpers[i].backtrace = nullptr;
   }
 
   // Tell the runner thread to exit its infinite loop.
@@ -708,8 +709,8 @@
 }
 
 TEST(libbacktrace, format_test) {
-  UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD));
-  ASSERT_TRUE(backtrace.get() != NULL);
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD));
+  ASSERT_TRUE(backtrace.get() != nullptr);
 
   backtrace_frame_data_t frame;
   frame.num = 1;
@@ -778,12 +779,12 @@
   return i.start < j.start;
 }
 
-static void VerifyMap(pid_t pid) {
+void VerifyMap(pid_t pid) {
   char buffer[4096];
   snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid);
 
   FILE* map_file = fopen(buffer, "r");
-  ASSERT_TRUE(map_file != NULL);
+  ASSERT_TRUE(map_file != nullptr);
   std::vector<map_test_t> test_maps;
   while (fgets(buffer, sizeof(buffer), map_file)) {
     map_test_t map;
@@ -793,7 +794,7 @@
   fclose(map_file);
   std::sort(test_maps.begin(), test_maps.end(), map_sort);
 
-  UniquePtr<BacktraceMap> map(BacktraceMap::Create(pid));
+  std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(pid));
 
   // Basic test that verifies that the map is in the expected order.
   std::vector<map_test_t>::const_iterator test_it = test_maps.begin();
@@ -827,7 +828,167 @@
   ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
 
   kill(pid, SIGKILL);
-  ASSERT_EQ(waitpid(pid, NULL, 0), pid);
+  ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
+}
+
+void* ThreadReadTest(void* data) {
+  thread_t* thread_data = reinterpret_cast<thread_t*>(data);
+
+  thread_data->tid = gettid();
+
+  // Create two map pages.
+  // Mark the second page as not-readable.
+  size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
+  uint8_t* memory;
+  if (posix_memalign(reinterpret_cast<void**>(&memory), pagesize, 2 * pagesize) != 0) {
+    return reinterpret_cast<void*>(-1);
+  }
+
+  if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
+    return reinterpret_cast<void*>(-1);
+  }
+
+  // Set up a simple pattern in memory.
+  for (size_t i = 0; i < pagesize; i++) {
+    memory[i] = i;
+  }
+
+  thread_data->data = memory;
+
+  // Tell the caller it's okay to start reading memory.
+  android_atomic_acquire_store(1, &thread_data->state);
+
+  // Loop waiting for everything
+  while (thread_data->state) {
+  }
+
+  free(memory);
+
+  android_atomic_acquire_store(1, &thread_data->state);
+
+  return nullptr;
+}
+
+void RunReadTest(Backtrace* backtrace, uintptr_t read_addr) {
+  size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
+
+  // Create a page of data to use to do quick compares.
+  uint8_t* expected = new uint8_t[pagesize];
+  for (size_t i = 0; i < pagesize; i++) {
+    expected[i] = i;
+  }
+  uint8_t* data = new uint8_t[2*pagesize];
+  // Verify that we can only read one page worth of data.
+  size_t bytes_read = backtrace->Read(read_addr, data, 2 * pagesize);
+  ASSERT_EQ(pagesize, bytes_read);
+  ASSERT_TRUE(memcmp(data, expected, pagesize) == 0);
+
+  // Verify unaligned reads.
+  for (size_t i = 1; i < sizeof(word_t); i++) {
+    bytes_read = backtrace->Read(read_addr + i, data, 2 * sizeof(word_t));
+    ASSERT_EQ(2 * sizeof(word_t), bytes_read);
+    ASSERT_TRUE(memcmp(data, &expected[i], 2 * sizeof(word_t)) == 0)
+        << "Offset at " << i << " failed";
+  }
+  delete data;
+  delete expected;
+}
+
+TEST(libbacktrace, thread_read) {
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  pthread_t thread;
+  thread_t thread_data = { 0, 0, 0, nullptr };
+  ASSERT_TRUE(pthread_create(&thread, &attr, ThreadReadTest, &thread_data) == 0);
+
+  ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10));
+
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
+  ASSERT_TRUE(backtrace.get() != nullptr);
+
+  RunReadTest(backtrace.get(), reinterpret_cast<uintptr_t>(thread_data.data));
+
+  android_atomic_acquire_store(0, &thread_data.state);
+
+  ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10));
+}
+
+volatile uintptr_t g_ready = 0;
+volatile uintptr_t g_addr = 0;
+
+void ForkedReadTest() {
+  // Create two map pages.
+  size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
+  uint8_t* memory;
+  if (posix_memalign(reinterpret_cast<void**>(&memory), pagesize, 2 * pagesize) != 0) {
+    perror("Failed to allocate memory\n");
+    exit(1);
+  }
+
+  // Mark the second page as not-readable.
+  if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
+    perror("Failed to mprotect memory\n");
+    exit(1);
+  }
+
+  // Set up a simple pattern in memory.
+  for (size_t i = 0; i < pagesize; i++) {
+    memory[i] = i;
+  }
+
+  g_addr = reinterpret_cast<uintptr_t>(memory);
+  g_ready = 1;
+
+  while (1) {
+    usleep(US_PER_MSEC);
+  }
+}
+
+TEST(libbacktrace, process_read) {
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    ForkedReadTest();
+    exit(0);
+  }
+  ASSERT_NE(-1, pid);
+
+  bool test_executed = false;
+  uint64_t start = NanoTime();
+  while (1) {
+    if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
+      WaitForStop(pid);
+
+      std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
+
+      uintptr_t read_addr;
+      size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_ready),
+                                          reinterpret_cast<uint8_t*>(&read_addr),
+                                          sizeof(uintptr_t));
+      ASSERT_EQ(sizeof(uintptr_t), bytes_read);
+      if (read_addr) {
+        // The forked process is ready to be read.
+        bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_addr),
+                                     reinterpret_cast<uint8_t*>(&read_addr),
+                                     sizeof(uintptr_t));
+        ASSERT_EQ(sizeof(uintptr_t), bytes_read);
+
+        RunReadTest(backtrace.get(), read_addr);
+
+        test_executed = true;
+        break;
+      }
+      ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
+    }
+    if ((NanoTime() - start) > 5 * NS_PER_SEC) {
+      break;
+    }
+    usleep(US_PER_MSEC);
+  }
+  kill(pid, SIGKILL);
+  ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
+
+  ASSERT_TRUE(test_executed);
 }
 
 #if defined(ENABLE_PSS_TESTS)
@@ -835,11 +996,11 @@
 
 #define MAX_LEAK_BYTES 32*1024UL
 
-static void CheckForLeak(pid_t pid, pid_t tid) {
+void CheckForLeak(pid_t pid, pid_t tid) {
   // Do a few runs to get the PSS stable.
   for (size_t i = 0; i < 100; i++) {
     Backtrace* backtrace = Backtrace::Create(pid, tid);
-    ASSERT_TRUE(backtrace != NULL);
+    ASSERT_TRUE(backtrace != nullptr);
     ASSERT_TRUE(backtrace->Unwind(0));
     delete backtrace;
   }
@@ -848,7 +1009,7 @@
   // Loop enough that even a small leak should be detectable.
   for (size_t i = 0; i < 4096; i++) {
     Backtrace* backtrace = Backtrace::Create(pid, tid);
-    ASSERT_TRUE(backtrace != NULL);
+    ASSERT_TRUE(backtrace != nullptr);
     ASSERT_TRUE(backtrace->Unwind(0));
     delete backtrace;
   }
@@ -863,9 +1024,9 @@
 }
 
 TEST(libbacktrace, check_for_leak_local_thread) {
-  thread_t thread_data = { 0, 0, 0 };
+  thread_t thread_data = { 0, 0, 0, nullptr };
   pthread_t thread;
-  ASSERT_TRUE(pthread_create(&thread, NULL, ThreadLevelRun, &thread_data) == 0);
+  ASSERT_TRUE(pthread_create(&thread, nullptr, ThreadLevelRun, &thread_data) == 0);
 
   // Wait up to 2 seconds for the tid to be set.
   ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
@@ -875,7 +1036,7 @@
   // Tell the thread to exit its infinite loop.
   android_atomic_acquire_store(0, &thread_data.state);
 
-  ASSERT_TRUE(pthread_join(thread, NULL) == 0);
+  ASSERT_TRUE(pthread_join(thread, nullptr) == 0);
 }
 
 TEST(libbacktrace, check_for_leak_remote) {
@@ -898,6 +1059,6 @@
   ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
 
   kill(pid, SIGKILL);
-  ASSERT_EQ(waitpid(pid, NULL, 0), pid);
+  ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
 }
 #endif
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index a865093..8f8cc3f 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -178,6 +178,10 @@
     static pid_t last_pid = (pid_t) -1;
     static atomic_int_fast32_t dropped;
 
+    if (!nr) {
+        return -EINVAL;
+    }
+
     if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
         last_uid = getuid();
     }
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index 0f7c384..70e37c6 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -72,14 +72,16 @@
         maxnaps = 1;
     }
 
-    while (maxnaps-- > 0) {
-        usleep(NAP_TIME * 1000);
+    while (maxnaps-- >= 0) {
         if (property_get(name, value, NULL)) {
             if (desired_value == NULL || 
                     strcmp(value, desired_value) == 0) {
                 return 0;
             }
         }
+        if (maxnaps >= 0) {
+            usleep(NAP_TIME * 1000);
+        }
     }
     return -1; /* failure */
 }
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index acd18b0..697db25 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -62,6 +62,8 @@
 LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
 LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
 LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS)
 LOCAL_SHARED_LIBRARIES := libcutils liblog
 
 # Really this should go away entirely or at least not depend on
@@ -74,22 +76,4 @@
 LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
 include $(BUILD_SHARED_LIBRARY)
 
-#
-# Static library version
-#
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= libpixelflinger_static
-LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
-LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm)
-LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
-LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
-LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
-# t32cb16blend.S does not compile with Clang.
-LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
-# arch-arm64/col32cb16blend.S does not compile with Clang.
-LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
-include $(BUILD_STATIC_LIBRARY)
-
-
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/include/pixelflinger/format.h b/libpixelflinger/include/pixelflinger/format.h
similarity index 100%
rename from include/pixelflinger/format.h
rename to libpixelflinger/include/pixelflinger/format.h
diff --git a/include/pixelflinger/pixelflinger.h b/libpixelflinger/include/pixelflinger/pixelflinger.h
similarity index 100%
rename from include/pixelflinger/pixelflinger.h
rename to libpixelflinger/include/pixelflinger/pixelflinger.h
diff --git a/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h
similarity index 100%
rename from include/private/pixelflinger/ggl_context.h
rename to libpixelflinger/include/private/pixelflinger/ggl_context.h
diff --git a/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
similarity index 100%
rename from include/private/pixelflinger/ggl_fixed.h
rename to libpixelflinger/include/private/pixelflinger/ggl_fixed.h
diff --git a/libpixelflinger/tests/arch-arm64/assembler/Android.mk b/libpixelflinger/tests/arch-arm64/assembler/Android.mk
index 961f323..448d298 100644
--- a/libpixelflinger/tests/arch-arm64/assembler/Android.mk
+++ b/libpixelflinger/tests/arch-arm64/assembler/Android.mk
@@ -13,7 +13,7 @@
     libpixelflinger
 
 LOCAL_C_INCLUDES := \
-    system/core/libpixelflinger
+    $(LOCAL_PATH)/../../..
 
 LOCAL_MODULE:= test-pixelflinger-arm64-assembler-test
 
diff --git a/libpixelflinger/tests/arch-arm64/disassembler/Android.mk b/libpixelflinger/tests/arch-arm64/disassembler/Android.mk
index 8f62f09..d8f7e69 100644
--- a/libpixelflinger/tests/arch-arm64/disassembler/Android.mk
+++ b/libpixelflinger/tests/arch-arm64/disassembler/Android.mk
@@ -7,9 +7,6 @@
 
 LOCAL_SHARED_LIBRARIES :=
 
-LOCAL_C_INCLUDES := \
-    system/core/libpixelflinger/codeflinger
-
 LOCAL_MODULE:= test-pixelflinger-arm64-disassembler-test
 
 LOCAL_MODULE_TAGS := tests
diff --git a/libpixelflinger/tests/codegen/Android.mk b/libpixelflinger/tests/codegen/Android.mk
index bc07015..2f9ca2f 100644
--- a/libpixelflinger/tests/codegen/Android.mk
+++ b/libpixelflinger/tests/codegen/Android.mk
@@ -9,7 +9,7 @@
     libpixelflinger
 
 LOCAL_C_INCLUDES := \
-	system/core/libpixelflinger
+	$(LOCAL_PATH)/../..
 
 LOCAL_MODULE:= test-opengl-codegen
 
diff --git a/libpixelflinger/tests/gglmul/Android.mk b/libpixelflinger/tests/gglmul/Android.mk
index f479fa1..75bd39e 100644
--- a/libpixelflinger/tests/gglmul/Android.mk
+++ b/libpixelflinger/tests/gglmul/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_SHARED_LIBRARIES :=
 
 LOCAL_C_INCLUDES := \
-	system/core/libpixelflinger
+	$(LOCAL_PATH)/../../include
 
 LOCAL_MODULE:= test-pixelflinger-gglmul
 
diff --git a/libsparse/sparse.c b/libsparse/sparse.c
index baa30cd..65c09e0 100644
--- a/libsparse/sparse.c
+++ b/libsparse/sparse.c
@@ -101,26 +101,32 @@
 	return chunks;
 }
 
-static void sparse_file_write_block(struct output_file *out,
+static int sparse_file_write_block(struct output_file *out,
 		struct backed_block *bb)
 {
+	int ret = -EINVAL;
+
 	switch (backed_block_type(bb)) {
 	case BACKED_BLOCK_DATA:
-		write_data_chunk(out, backed_block_len(bb), backed_block_data(bb));
+		ret = write_data_chunk(out, backed_block_len(bb), backed_block_data(bb));
 		break;
 	case BACKED_BLOCK_FILE:
-		write_file_chunk(out, backed_block_len(bb),
-				backed_block_filename(bb), backed_block_file_offset(bb));
+		ret = write_file_chunk(out, backed_block_len(bb),
+				       backed_block_filename(bb),
+				       backed_block_file_offset(bb));
 		break;
 	case BACKED_BLOCK_FD:
-		write_fd_chunk(out, backed_block_len(bb),
-				backed_block_fd(bb), backed_block_file_offset(bb));
+		ret = write_fd_chunk(out, backed_block_len(bb),
+				     backed_block_fd(bb),
+				     backed_block_file_offset(bb));
 		break;
 	case BACKED_BLOCK_FILL:
-		write_fill_chunk(out, backed_block_len(bb),
-				backed_block_fill_val(bb));
+		ret = write_fill_chunk(out, backed_block_len(bb),
+				       backed_block_fill_val(bb));
 		break;
 	}
+
+	return ret;
 }
 
 static int write_all_blocks(struct sparse_file *s, struct output_file *out)
@@ -128,6 +134,7 @@
 	struct backed_block *bb;
 	unsigned int last_block = 0;
 	int64_t pad;
+	int ret = 0;
 
 	for (bb = backed_block_iter_new(s->backed_block_list); bb;
 			bb = backed_block_iter_next(bb)) {
@@ -135,7 +142,9 @@
 			unsigned int blocks = backed_block_block(bb) - last_block;
 			write_skip_chunk(out, (int64_t)blocks * s->block_size);
 		}
-		sparse_file_write_block(out, bb);
+		ret = sparse_file_write_block(out, bb);
+		if (ret)
+			return ret;
 		last_block = backed_block_block(bb) +
 				DIV_ROUND_UP(backed_block_len(bb), s->block_size);
 	}
@@ -230,6 +239,7 @@
 	struct backed_block *bb;
 	struct backed_block *start;
 	int64_t file_len = 0;
+	int ret;
 
 	/*
 	 * overhead is sparse file header, initial skip chunk, split chunk, end
@@ -249,7 +259,11 @@
 	for (bb = start; bb; bb = backed_block_iter_next(bb)) {
 		count = 0;
 		/* will call out_counter_write to update count */
-		sparse_file_write_block(out_counter, bb);
+		ret = sparse_file_write_block(out_counter, bb);
+		if (ret) {
+			bb = NULL;
+			goto out;
+		}
 		if (file_len + count > len) {
 			/*
 			 * If the remaining available size is more than 1/8th of the
@@ -260,16 +274,17 @@
 				backed_block_split(from->backed_block_list, bb, len - file_len);
 				last_bb = bb;
 			}
-			goto out;
+			goto move;
 		}
 		file_len += count;
 		last_bb = bb;
 	}
 
-out:
+move:
 	backed_block_list_move(from->backed_block_list,
 		to->backed_block_list, start, last_bb);
 
+out:
 	output_file_close(out_counter);
 
 	return bb;
diff --git a/libutils/Android.mk b/libutils/Android.mk
index 7bff14e..e9c5f89 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -39,9 +39,7 @@
 	Tokenizer.cpp \
 	Unicode.cpp \
 	VectorImpl.cpp \
-	file.cpp \
 	misc.cpp \
-	stringprintf.cpp \
 
 host_commonCflags := -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -Werror
 
diff --git a/libutils/tests/Android.mk b/libutils/tests/Android.mk
index ce288ca..634f44f 100644
--- a/libutils/tests/Android.mk
+++ b/libutils/tests/Android.mk
@@ -26,11 +26,9 @@
     BasicHashtable_test.cpp \
     BlobCache_test.cpp \
     BitSet_test.cpp \
-    file_test.cpp \
     Looper_test.cpp \
     LruCache_test.cpp \
     String8_test.cpp \
-    stringprintf_test.cpp \
     Unicode_test.cpp \
     Vector_test.cpp \
 
diff --git a/libziparchive/testdata/declaredlength.zip b/libziparchive/testdata/declaredlength.zip
new file mode 100644
index 0000000..773380c
--- /dev/null
+++ b/libziparchive/testdata/declaredlength.zip
Binary files differ
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index e820f2a..6475649 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -824,7 +824,7 @@
   // name in the central directory.
   if (lfh->file_name_length == nameLen) {
     const off64_t name_offset = local_header_offset + sizeof(LocalFileHeader);
-    if (name_offset + lfh->file_name_length >= cd_offset) {
+    if (name_offset + lfh->file_name_length > cd_offset) {
       ALOGW("Zip: Invalid declared length");
       return kInvalidOffset;
     }
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index c8dafa9..64faa6d 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -171,6 +171,22 @@
   CloseArchive(handle);
 }
 
+TEST(ziparchive, TestInvalidDeclaredLength) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle));
+
+  void* iteration_cookie;
+  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL));
+
+  ZipEntryName name;
+  ZipEntry data;
+
+  ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
+  ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
+
+  CloseArchive(handle);
+}
+
 TEST(ziparchive, ExtractToMemory) {
   ZipArchiveHandle handle;
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
diff --git a/libzipfile/zipfile.c b/libzipfile/zipfile.c
index b903fcf..1032ecc 100644
--- a/libzipfile/zipfile.c
+++ b/libzipfile/zipfile.c
@@ -76,7 +76,7 @@
 };
 
 static int
-uninflate(unsigned char* out, int unlen, const unsigned char* in, int clen)
+inflate_wrapper(unsigned char* out, int unlen, const unsigned char* in, int clen)
 {
     z_stream zstream;
     int err = 0;
@@ -121,7 +121,7 @@
             memcpy(buf, entry->data, entry->uncompressedSize);
             return 0;
         case DEFLATED:
-            return uninflate(buf, bufsize, entry->data, entry->compressedSize);
+            return inflate_wrapper(buf, bufsize, entry->data, entry->compressedSize);
         default:
             return -1;
     }
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index 3be07c0..26a1861 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -27,7 +27,7 @@
                            unsigned long tail,
                            unsigned int logMask,
                            pid_t pid,
-                           log_time start)
+                           uint64_t start)
         : mReader(reader)
         , mNonBlock(nonBlock)
         , mTail(tail)
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index f34c06a..61c6858 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -31,7 +31,7 @@
     unsigned long mTail;
     unsigned int mLogMask;
     pid_t mPid;
-    log_time mStart;
+    uint64_t mStart;
 
 public:
     FlushCommand(LogReader &mReader,
@@ -39,7 +39,7 @@
                  unsigned long tail = -1,
                  unsigned int logMask = -1,
                  pid_t pid = 0,
-                 log_time start = LogTimeEntry::EPOCH);
+                 uint64_t start = 1);
     virtual void runSocketCommand(SocketClient *client);
 
     static bool hasReadLogs(SocketClient *client);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 2b495ab..2693583 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -161,7 +161,7 @@
     if (last == mLogElements.end()) {
         mLogElements.push_back(elem);
     } else {
-        log_time end = log_time::EPOCH;
+        uint64_t end = 1;
         bool end_set = false;
         bool end_always = false;
 
@@ -184,7 +184,7 @@
         }
 
         if (end_always
-                || (end_set && (end >= (*last)->getMonotonicTime()))) {
+                || (end_set && (end >= (*last)->getSequence()))) {
             mLogElements.push_back(elem);
         } else {
             mLogElements.insert(last,elem);
@@ -241,7 +241,7 @@
         for(it = mLogElements.begin(); it != mLogElements.end();) {
             LogBufferElement *e = *it;
 
-            if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+            if (oldest && (oldest->mStart <= e->getSequence())) {
                 break;
             }
 
@@ -293,7 +293,7 @@
         for(it = mLogElements.begin(); it != mLogElements.end();) {
             LogBufferElement *e = *it;
 
-            if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+            if (oldest && (oldest->mStart <= e->getSequence())) {
                 break;
             }
 
@@ -334,7 +334,7 @@
     while((pruneRows > 0) && (it != mLogElements.end())) {
         LogBufferElement *e = *it;
         if (e->getLogId() == id) {
-            if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+            if (oldest && (oldest->mStart <= e->getSequence())) {
                 if (!whitelist) {
                     if (stats.sizes(id) > (2 * log_buffer_size(id))) {
                         // kick a misbehaving log reader client off the island
@@ -366,7 +366,7 @@
         while((it != mLogElements.end()) && (pruneRows > 0)) {
             LogBufferElement *e = *it;
             if (e->getLogId() == id) {
-                if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+                if (oldest && (oldest->mStart <= e->getSequence())) {
                     if (stats.sizes(id) > (2 * log_buffer_size(id))) {
                         // kick a misbehaving log reader client off the island
                         oldest->release_Locked();
@@ -423,16 +423,16 @@
     return retval;
 }
 
-log_time LogBuffer::flushTo(
-        SocketClient *reader, const log_time start, bool privileged,
-        bool (*filter)(const LogBufferElement *element, void *arg), void *arg) {
+uint64_t LogBuffer::flushTo(
+        SocketClient *reader, const uint64_t start, bool privileged,
+        int (*filter)(const LogBufferElement *element, void *arg), void *arg) {
     LogBufferElementCollection::iterator it;
-    log_time max = start;
+    uint64_t max = start;
     uid_t uid = reader->getUid();
 
     pthread_mutex_lock(&mLogElementsLock);
 
-    if (start == LogTimeEntry::EPOCH) {
+    if (start <= 1) {
         // client wants to start from the beginning
         it = mLogElements.begin();
     } else {
@@ -441,7 +441,7 @@
         for (it = mLogElements.end(); it != mLogElements.begin(); /* do nothing */) {
             --it;
             LogBufferElement *element = *it;
-            if (element->getMonotonicTime() <= start) {
+            if (element->getSequence() <= start) {
                 it++;
                 break;
             }
@@ -455,13 +455,19 @@
             continue;
         }
 
-        if (element->getMonotonicTime() <= start) {
+        if (element->getSequence() <= start) {
             continue;
         }
 
         // NB: calling out to another object with mLogElementsLock held (safe)
-        if (filter && !(*filter)(element, arg)) {
-            continue;
+        if (filter) {
+            int ret = (*filter)(element, arg);
+            if (ret == false) {
+                continue;
+            }
+            if (ret != true) {
+                break;
+            }
         }
 
         pthread_mutex_unlock(&mLogElementsLock);
@@ -481,7 +487,7 @@
 }
 
 void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
-    log_time oldest(CLOCK_MONOTONIC);
+    uint64_t oldest = UINT64_MAX;
 
     pthread_mutex_lock(&mLogElementsLock);
 
@@ -491,7 +497,7 @@
         LogBufferElement *element = *it;
 
         if ((logMask & (1 << element->getLogId()))) {
-            oldest = element->getMonotonicTime();
+            oldest = element->getSequence();
             break;
         }
     }
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 86a2a2a..13e6aa8 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -51,9 +51,9 @@
     void log(log_id_t log_id, log_time realtime,
              uid_t uid, pid_t pid, pid_t tid,
              const char *msg, unsigned short len);
-    log_time flushTo(SocketClient *writer, const log_time start,
+    uint64_t flushTo(SocketClient *writer, const uint64_t start,
                      bool privileged,
-                     bool (*filter)(const LogBufferElement *element, void *arg) = NULL,
+                     int (*filter)(const LogBufferElement *element, void *arg) = NULL,
                      void *arg = NULL);
 
     void clear(log_id_t id, uid_t uid = AID_ROOT);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index d959ceb..5e780b5 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -24,7 +24,8 @@
 #include "LogBufferElement.h"
 #include "LogReader.h"
 
-const log_time LogBufferElement::FLUSH_ERROR((uint32_t)0, (uint32_t)0);
+const uint64_t LogBufferElement::FLUSH_ERROR(0);
+atomic_int_fast64_t LogBufferElement::sequence;
 
 LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
                                    uid_t uid, pid_t pid, pid_t tid,
@@ -34,7 +35,7 @@
         , mPid(pid)
         , mTid(tid)
         , mMsgLen(len)
-        , mMonotonicTime(CLOCK_MONOTONIC)
+        , mSequence(sequence.fetch_add(1, memory_order_relaxed))
         , mRealTime(realtime) {
     mMsg = new char[len];
     memcpy(mMsg, msg, len);
@@ -44,7 +45,7 @@
     delete [] mMsg;
 }
 
-log_time LogBufferElement::flushTo(SocketClient *reader) {
+uint64_t LogBufferElement::flushTo(SocketClient *reader) {
     struct logger_entry_v3 entry;
     memset(&entry, 0, sizeof(struct logger_entry_v3));
     entry.hdr_size = sizeof(struct logger_entry_v3);
@@ -64,5 +65,5 @@
         return FLUSH_ERROR;
     }
 
-    return mMonotonicTime;
+    return mSequence;
 }
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index fdca973..25f1450 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -18,6 +18,7 @@
 #define _LOGD_LOG_BUFFER_ELEMENT_H__
 
 #include <sys/types.h>
+#include <stdatomic.h>
 #include <sysutils/SocketClient.h>
 #include <log/log.h>
 #include <log/log_read.h>
@@ -29,8 +30,9 @@
     const pid_t mTid;
     char *mMsg;
     const unsigned short mMsgLen;
-    const log_time mMonotonicTime;
+    const uint64_t mSequence;
     const log_time mRealTime;
+    static atomic_int_fast64_t sequence;
 
 public:
     LogBufferElement(log_id_t log_id, log_time realtime,
@@ -43,11 +45,12 @@
     pid_t getPid(void) const { return mPid; }
     pid_t getTid(void) const { return mTid; }
     unsigned short getMsgLen() const { return mMsgLen; }
-    log_time getMonotonicTime(void) const { return mMonotonicTime; }
+    uint64_t getSequence(void) const { return mSequence; }
+    static uint64_t getCurrentSequence(void) { return sequence.load(memory_order_relaxed); }
     log_time getRealTime(void) const { return mRealTime; }
 
-    static const log_time FLUSH_ERROR;
-    log_time flushTo(SocketClient *writer);
+    static const uint64_t FLUSH_ERROR;
+    uint64_t flushTo(SocketClient *writer);
 };
 
 #endif
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 26df087..f7df275 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -100,50 +100,51 @@
         nonBlock = true;
     }
 
-    // Convert realtime to monotonic time
-    if (start == log_time::EPOCH) {
-        start = LogTimeEntry::EPOCH;
-    } else {
+    uint64_t sequence = 1;
+    // Convert realtime to sequence number
+    if (start != log_time::EPOCH) {
         class LogFindStart {
             const pid_t mPid;
             const unsigned mLogMask;
             bool startTimeSet;
             log_time &start;
-            log_time last;
+            uint64_t &sequence;
+            uint64_t last;
 
         public:
-            LogFindStart(unsigned logMask, pid_t pid, log_time &start)
+            LogFindStart(unsigned logMask, pid_t pid, log_time &start, uint64_t &sequence)
                     : mPid(pid)
                     , mLogMask(logMask)
                     , startTimeSet(false)
                     , start(start)
-                    , last(LogTimeEntry::EPOCH)
+                    , sequence(sequence)
+                    , last(sequence)
             { }
 
-            static bool callback(const LogBufferElement *element, void *obj) {
+            static int callback(const LogBufferElement *element, void *obj) {
                 LogFindStart *me = reinterpret_cast<LogFindStart *>(obj);
-                if (!me->startTimeSet
-                        && (!me->mPid || (me->mPid == element->getPid()))
+                if ((!me->mPid || (me->mPid == element->getPid()))
                         && (me->mLogMask & (1 << element->getLogId()))) {
                     if (me->start == element->getRealTime()) {
-                        me->start = element->getMonotonicTime();
+                        me->sequence = element->getSequence();
                         me->startTimeSet = true;
+                        return -1;
                     } else {
                         if (me->start < element->getRealTime()) {
-                            me->start = me->last;
+                            me->sequence = me->last;
                             me->startTimeSet = true;
+                            return -1;
                         }
-                        me->last = element->getMonotonicTime();
+                        me->last = element->getSequence();
                     }
                 }
                 return false;
             }
 
             bool found() { return startTimeSet; }
-        } logFindStart(logMask, pid, start);
+        } logFindStart(logMask, pid, start, sequence);
 
-        logbuf().flushTo(cli, LogTimeEntry::EPOCH,
-                         FlushCommand::hasReadLogs(cli),
+        logbuf().flushTo(cli, sequence, FlushCommand::hasReadLogs(cli),
                          logFindStart.callback, &logFindStart);
 
         if (!logFindStart.found()) {
@@ -151,12 +152,11 @@
                 doSocketDelete(cli);
                 return false;
             }
-            log_time now(CLOCK_MONOTONIC);
-            start = now;
+            sequence = LogBufferElement::getCurrentSequence();
         }
     }
 
-    FlushCommand command(*this, nonBlock, tail, logMask, pid, start);
+    FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence);
     command.runSocketCommand(cli);
     return true;
 }
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
index 5f9db8d..1b60b7e 100644
--- a/logd/LogTimes.cpp
+++ b/logd/LogTimes.cpp
@@ -23,12 +23,10 @@
 
 pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
 
-const struct timespec LogTimeEntry::EPOCH = { 0, 1 };
-
 LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client,
                            bool nonBlock, unsigned long tail,
                            unsigned int logMask, pid_t pid,
-                           log_time start)
+                           uint64_t start)
         : mRefCount(1)
         , mRelease(false)
         , mError(false)
@@ -42,7 +40,7 @@
         , mClient(client)
         , mStart(start)
         , mNonBlock(nonBlock)
-        , mEnd(CLOCK_MONOTONIC)
+        , mEnd(LogBufferElement::getCurrentSequence())
 {
         pthread_cond_init(&threadTriggeredCondition, NULL);
         cleanSkip_Locked();
@@ -129,7 +127,7 @@
     lock();
 
     while (me->threadRunning && !me->isError_Locked()) {
-        log_time start = me->mStart;
+        uint64_t start = me->mStart;
 
         unlock();
 
@@ -161,13 +159,13 @@
 }
 
 // A first pass to count the number of elements
-bool LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) {
+int LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) {
     LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
 
     LogTimeEntry::lock();
 
     if (me->mCount == 0) {
-        me->mStart = element->getMonotonicTime();
+        me->mStart = element->getSequence();
     }
 
     if ((!me->mPid || (me->mPid == element->getPid()))
@@ -181,12 +179,12 @@
 }
 
 // A second pass to send the selected elements
-bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) {
+int LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) {
     LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
 
     LogTimeEntry::lock();
 
-    me->mStart = element->getMonotonicTime();
+    me->mStart = element->getSequence();
 
     if (me->skipAhead[element->getLogId()]) {
         me->skipAhead[element->getLogId()]--;
@@ -195,7 +193,7 @@
 
     // Truncate to close race between first and second pass
     if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
-        goto skip;
+        goto stop;
     }
 
     if (!me->isWatching(element->getLogId())) {
@@ -207,7 +205,7 @@
     }
 
     if (me->isError_Locked()) {
-        goto skip;
+        goto stop;
     }
 
     if (!me->mTail) {
@@ -234,6 +232,10 @@
 skip:
     LogTimeEntry::unlock();
     return false;
+
+stop:
+    LogTimeEntry::unlock();
+    return -1;
 }
 
 void LogTimeEntry::cleanSkip_Locked(void) {
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 81aedfb..ae2f92b 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -47,13 +47,12 @@
 public:
     LogTimeEntry(LogReader &reader, SocketClient *client, bool nonBlock,
                  unsigned long tail, unsigned int logMask, pid_t pid,
-                 log_time start);
+                 uint64_t start);
 
     SocketClient *mClient;
-    static const struct timespec EPOCH;
-    log_time mStart;
+    uint64_t mStart;
     const bool mNonBlock;
-    const log_time mEnd; // only relevant if mNonBlock
+    const uint64_t mEnd; // only relevant if mNonBlock
 
     // Protect List manipulations
     static void lock(void) { pthread_mutex_lock(&timesLock); }
@@ -103,8 +102,8 @@
     }
     bool isWatching(log_id_t id) { return (mLogMask & (1<<id)) != 0; }
     // flushTo filter callbacks
-    static bool FilterFirstPass(const LogBufferElement *element, void *me);
-    static bool FilterSecondPass(const LogBufferElement *element, void *me);
+    static int FilterFirstPass(const LogBufferElement *element, void *me);
+    static int FilterSecondPass(const LogBufferElement *element, void *me);
 };
 
 typedef android::List<LogTimeEntry *> LastLogTimes;
diff --git a/netcfg/Android.mk b/netcfg/Android.mk
deleted file mode 100644
index 4796c11..0000000
--- a/netcfg/Android.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= netcfg.c
-LOCAL_MODULE:= netcfg
-LOCAL_SHARED_LIBRARIES := libnetutils
-LOCAL_CFLAGS := -Werror
-include $(BUILD_EXECUTABLE)
diff --git a/netcfg/MODULE_LICENSE_APACHE2 b/netcfg/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/netcfg/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/netcfg/NOTICE b/netcfg/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/netcfg/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2005-2008, 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.
-
-   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.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/netcfg/netcfg.c b/netcfg/netcfg.c
deleted file mode 100644
index eec1b2f..0000000
--- a/netcfg/netcfg.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#include <errno.h>
-#include <dirent.h>
-#include <netinet/ether.h>
-#include <netinet/if_ether.h>
-#include <netutils/dhcp.h>
-#include <netutils/ifc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static const char *ipaddr(in_addr_t addr)
-{
-    struct in_addr in_addr;
-
-    in_addr.s_addr = addr;
-    return inet_ntoa(in_addr);
-}
-
-static void usage(void)
-{
-    fprintf(stderr,"usage: netcfg [<interface> dhcp]\n");
-    exit(1);
-}
-
-static int dump_interface(const char *name)
-{
-    unsigned addr, flags;
-    unsigned char hwbuf[ETH_ALEN];
-    int prefixLength;
-
-    if(ifc_get_info(name, &addr, &prefixLength, &flags)) {
-        return 0;
-    }
-
-    printf("%-8s %s  ", name, flags & 1 ? "UP  " : "DOWN");
-    printf("%40s", ipaddr(addr));
-    printf("/%-4d", prefixLength);
-    printf("0x%08x ", flags);
-    if (!ifc_get_hwaddr(name, hwbuf)) {
-        int i;
-        for(i=0; i < (ETH_ALEN-1); i++)
-            printf("%02x:", hwbuf[i]);
-        printf("%02x\n", hwbuf[i]);
-    } else {
-        printf("\n");
-    }
-    return 0;
-}
-
-static int dump_interfaces(void)
-{
-    DIR *d;
-    struct dirent *de;
-
-    d = opendir("/sys/class/net");
-    if(d == 0) return -1;
-
-    while((de = readdir(d))) {
-        if(de->d_name[0] == '.') continue;
-        dump_interface(de->d_name);
-    }
-    closedir(d);
-    return 0;
-}
-
-int main(int argc, char **argv)
-{
-    if(ifc_init()) {
-        perror("Cannot perform requested operation");
-        exit(1);
-    }
-
-    if(argc == 1) {
-        int result = dump_interfaces();
-        ifc_close();
-        return result;
-    }
-
-    if(argc != 3) usage();
-
-    char* iname = argv[1];
-    char* action = argv[2];
-    if(strlen(iname) > 16) usage();
-
-    if (!strcmp(action, "dhcp")) {
-        if (do_dhcp(iname)) {
-            fprintf(stderr, "dhcp failed: %s\n", strerror(errno));
-            ifc_close();
-            exit(1);
-        }
-    } else {
-        fprintf(stderr,"no such action '%s'\n", action);
-        usage();
-    }
-
-    ifc_close();
-    return 0;
-}
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 30bef46..0064790 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -1,6 +1,5 @@
 # set up the global environment
 on init
-    export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
     export ANDROID_BOOTLOGO 1
     export ANDROID_ROOT /system
     export ANDROID_ASSETS /system/app
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index 63b0f41..cb3a8fb 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -6,6 +6,6 @@
 LOCAL_MODULE := sdcard
 LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
 
-LOCAL_SHARED_LIBRARIES := libc libcutils
+LOCAL_SHARED_LIBRARIES := libcutils
 
 include $(BUILD_EXECUTABLE)
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 424ba23..959dc22 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -60,10 +60,8 @@
     restorecon \
     route \
     runcon \
-    schedtop \
     sendevent \
     setprop \
-    smd \
     start \
     stop \
     top \
diff --git a/toolbox/schedtop.c b/toolbox/schedtop.c
deleted file mode 100644
index 2fccd2e..0000000
--- a/toolbox/schedtop.c
+++ /dev/null
@@ -1,330 +0,0 @@
-#include <ctype.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-struct thread_info {
-    int pid;
-    int tid;
-    char name[64];
-    unsigned long long exec_time;
-    unsigned long long delay_time;
-    unsigned long long run_count;
-};
-
-struct thread_table {
-    size_t allocated;
-    size_t active;
-    struct thread_info *data;
-};
-
-enum {
-    FLAG_BATCH = 1U << 0,
-    FLAG_HIDE_IDLE = 1U << 1,
-    FLAG_SHOW_THREADS = 1U << 2,
-    FLAG_USE_ALTERNATE_SCREEN = 1U << 3,
-};
-
-static int time_dp = 9;
-static int time_div = 1;
-#define NS_TO_S_D(ns) \
-    (uint32_t)((ns) / 1000000000), time_dp, ((uint32_t)((ns) % 1000000000) / time_div)
-
-struct thread_table processes;
-struct thread_table last_processes;
-struct thread_table threads;
-struct thread_table last_threads;
-
-static void grow_table(struct thread_table *table)
-{
-    size_t size = table->allocated;
-    struct thread_info *new_table;
-    if (size < 128)
-        size = 128;
-    else
-        size *= 2;
-    
-    new_table = realloc(table->data, size * sizeof(*table->data));
-    if (new_table == NULL) {
-        fprintf(stderr, "out of memory\n");
-        exit(1);
-    }
-    table->data = new_table;
-    table->allocated = size;
-}
-
-static struct thread_info *get_item(struct thread_table *table)
-{
-    if (table->active >= table->allocated)
-        grow_table(table);
-    return table->data + table->active;
-}
-
-static void commit_item(struct thread_table *table)
-{
-    table->active++;
-}
-
-static int read_line(char *line, size_t line_size)
-{
-    int fd;
-    int len;
-    fd = open(line, O_RDONLY);
-    if(fd == 0)
-        return -1;
-    len = read(fd, line, line_size - 1);
-    close(fd);
-    if (len <= 0)
-        return -1;
-    line[len] = '\0';
-    return 0;
-}
-
-static void add_thread(int pid, int tid, struct thread_info *proc_info)
-{
-    char line[1024];
-    char *name, *name_end;
-    size_t name_len;
-    struct thread_info *info;
-    if(tid == 0)
-        info = get_item(&processes);
-    else
-        info = get_item(&threads);
-    info->pid = pid;
-    info->tid = tid;
-
-    if(tid)
-        sprintf(line, "/proc/%d/task/%d/schedstat", pid, tid);
-    else
-        sprintf(line, "/proc/%d/schedstat", pid);
-    if (read_line(line, sizeof(line)))
-        return;
-    if(sscanf(line, "%llu %llu %llu",
-              &info->exec_time, &info->delay_time, &info->run_count) != 3)
-        return;
-    if (proc_info) {
-        proc_info->exec_time += info->exec_time;
-        proc_info->delay_time += info->delay_time;
-        proc_info->run_count += info->run_count;
-    }
-
-    name = NULL;
-    if (!tid) {
-        sprintf(line, "/proc/%d/cmdline", pid);
-        if (read_line(line, sizeof(line)) == 0 && line[0]) {
-            name = line;
-            name_len = strlen(name);
-        }
-    }
-    if (!name) {
-        if (tid)
-            sprintf(line, "/proc/%d/task/%d/stat", pid, tid);
-        else
-            sprintf(line, "/proc/%d/stat", pid);
-        if (read_line(line, sizeof(line)))
-            return;
-        name = strchr(line, '(');
-        if (name == NULL)
-            return;
-        name_end = strchr(name, ')');
-        if (name_end == NULL)
-            return;
-        name++;
-        name_len = name_end - name;
-    }
-    if (name_len >= sizeof(info->name))
-        name_len = sizeof(info->name) - 1;
-    memcpy(info->name, name, name_len);
-    info->name[name_len] = '\0';
-    if(tid == 0)
-        commit_item(&processes);
-    else
-        commit_item(&threads);
-}
-
-static void add_threads(int pid, struct thread_info *proc_info)
-{
-    char path[1024];
-    DIR *d;
-    struct dirent *de;
-    sprintf(path, "/proc/%d/task", pid);
-    d = opendir(path);
-    if(d == 0) return;
-    while((de = readdir(d)) != 0){
-        if(isdigit(de->d_name[0])){
-            int tid = atoi(de->d_name);
-            add_thread(pid, tid, proc_info);
-        }
-    }
-    closedir(d);
-}
-
-static void print_threads(int pid, uint32_t flags)
-{
-    size_t i, j;
-    for (i = 0; i < last_threads.active; i++) {
-        int epid = last_threads.data[i].pid;
-        int tid = last_threads.data[i].tid;
-        if (epid != pid)
-            continue;
-        for (j = 0; j < threads.active; j++)
-            if (tid == threads.data[j].tid)
-                break;
-        if (j == threads.active)
-            printf(" %5u died\n", tid);
-        else if (!(flags & FLAG_HIDE_IDLE) || threads.data[j].run_count - last_threads.data[i].run_count)
-            printf(" %5u %2u.%0*u %2u.%0*u %5llu %5u.%0*u %5u.%0*u %7llu  %s\n", tid,
-                NS_TO_S_D(threads.data[j].exec_time - last_threads.data[i].exec_time),
-                NS_TO_S_D(threads.data[j].delay_time - last_threads.data[i].delay_time),
-                threads.data[j].run_count - last_threads.data[i].run_count,
-                NS_TO_S_D(threads.data[j].exec_time), NS_TO_S_D(threads.data[j].delay_time),
-                threads.data[j].run_count, threads.data[j].name);
-    }
-}
-
-static void update_table(DIR *d, uint32_t flags)
-{
-    size_t i, j;
-    struct dirent *de;
-    
-    rewinddir(d);
-    while((de = readdir(d)) != 0){
-        if(isdigit(de->d_name[0])){
-            int pid = atoi(de->d_name);
-            struct thread_info *proc_info;
-            add_thread(pid, 0, NULL);
-            proc_info = &processes.data[processes.active - 1];
-            proc_info->exec_time = 0;
-            proc_info->delay_time = 0;
-            proc_info->run_count = 0;
-            add_threads(pid, proc_info);
-        }
-    }
-    if (!(flags & FLAG_BATCH))
-        printf("\e[H\e[0J");
-    printf("Processes: %zu, Threads %zu\n", processes.active, threads.active);
-    switch (time_dp) {
-    case 3:
-        printf("   TID --- SINCE LAST ---- ---------- TOTAL ----------\n");
-        printf("  PID  EXEC_T  DELAY SCHED EXEC_TIME DELAY_TIM   SCHED NAME\n");
-        break;
-    case 6:
-        printf("   TID ------ SINCE LAST -------    ------------ TOTAL -----------\n");
-        printf("  PID  EXEC_TIME DELAY_TIM SCHED    EXEC_TIME   DELAY_TIME   SCHED NAME\n");
-        break;
-    default:
-        printf("   TID    -------- SINCE LAST --------       ------------- TOTAL -------------\n");
-        printf("  PID     EXEC_TIME   DELAY_TIME SCHED       EXEC_TIME      DELAY_TIME   SCHED NAME\n");
-        break;
-    }
-    for (i = 0; i < last_processes.active; i++) {
-        int pid = last_processes.data[i].pid;
-        for (j = 0; j < processes.active; j++)
-            if (pid == processes.data[j].pid)
-                break;
-        if (j == processes.active)
-            printf("%5u died\n", pid);
-        else if (!(flags & FLAG_HIDE_IDLE) || processes.data[j].run_count - last_processes.data[i].run_count) {
-            printf("%5u  %2u.%0*u %2u.%0*u %5llu %5u.%0*u %5u.%0*u %7llu %s\n", pid,
-                NS_TO_S_D(processes.data[j].exec_time - last_processes.data[i].exec_time),
-                NS_TO_S_D(processes.data[j].delay_time - last_processes.data[i].delay_time),
-                processes.data[j].run_count - last_processes.data[i].run_count,
-                NS_TO_S_D(processes.data[j].exec_time), NS_TO_S_D(processes.data[j].delay_time),
-                processes.data[j].run_count, processes.data[j].name);
-            if (flags & FLAG_SHOW_THREADS)
-                print_threads(pid, flags);
-        }
-    }
-
-    {
-        struct thread_table tmp;
-        tmp = last_processes;
-        last_processes = processes;
-        processes = tmp;
-        processes.active = 0;
-        tmp = last_threads;
-        last_threads = threads;
-        threads = tmp;
-        threads.active = 0;
-    }
-}
-
-void
-sig_abort(int signum)
-{
-    printf("\e[?47l");
-    exit(0);
-}
-
-
-int schedtop_main(int argc, char **argv)
-{
-    int c;
-    DIR *d;
-    uint32_t flags = 0;    
-    int delay = 3000000;
-    float delay_f;
-
-    while(1) {
-        c = getopt(argc, argv, "d:ibtamun");
-        if (c == EOF)
-            break;
-        switch (c) {
-        case 'd':
-            delay_f = atof(optarg);
-            delay = delay_f * 1000000;
-            break;
-        case 'b':
-            flags |= FLAG_BATCH;
-            break;
-        case 'i':
-            flags |= FLAG_HIDE_IDLE;
-            break;
-        case 't':
-            flags |= FLAG_SHOW_THREADS;
-            break;
-        case 'a':
-            flags |= FLAG_USE_ALTERNATE_SCREEN;
-            break;
-        case 'm':
-            time_dp = 3;
-            time_div = 1000000;
-            break;
-        case 'u':
-            time_dp = 6;
-            time_div = 1000;
-            break;
-        case 'n':
-            time_dp = 9;
-            time_div = 1;
-            break;
-        }
-    }
-
-    d = opendir("/proc");
-    if(d == 0) return -1;
-
-    if (!(flags & FLAG_BATCH)) {
-        if(flags & FLAG_USE_ALTERNATE_SCREEN) {
-            signal(SIGINT, sig_abort);
-            signal(SIGPIPE, sig_abort);
-            signal(SIGTERM, sig_abort);
-            printf("\e7\e[?47h");
-        }
-        printf("\e[2J");
-    }
-    while (1) {
-        update_table(d, flags);
-        usleep(delay);
-    }
-    closedir(d);
-    return 0;
-}
diff --git a/toolbox/smd.c b/toolbox/smd.c
deleted file mode 100644
index 343dea7..0000000
--- a/toolbox/smd.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-
-int smd_main(int argc, char **argv)
-{
-    int fd, len, r, port = 0;
-    char devname[32];
-    argc--;
-    argv++;
-
-    if((argc > 0) && (argv[0][0] == '-')) {
-        port = atoi(argv[0] + 1);
-        argc--;
-        argv++;
-    }
-
-    sprintf(devname,"/dev/smd%d",port);
-    fd = open(devname, O_WRONLY);
-    if(fd < 0) {
-        fprintf(stderr,"failed to open smd0 - %s\n",
-            strerror(errno));
-        return -1;
-    }
-    while(argc > 0) {
-        len = strlen(argv[0]);
-        r = write(fd, argv[0], len);
-        if(r != len) {
-            fprintf(stderr,"failed to write smd0 (%d) %s\n",
-                r, strerror(errno));
-            return -1;
-        }
-        argc--;
-        argv++;
-        write(fd, argc ? " " : "\r", 1);
-    }
-    close(fd);
-    return 0;       
-}