Merge "Use fsck.f2fs -a instead of -f for faster boot"
diff --git a/adb/adb.h b/adb/adb.h
index 1be83d7..31fe3a5 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -365,7 +365,9 @@
 
 extern const char *adb_device_banner;
 extern int HOST;
+#if !ADB_HOST
 extern int SHELL_EXIT_NOTIFY_FD;
+#endif // !ADB_HOST
 
 #define CHUNK_SIZE (64*1024)
 
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index a335eec..641b537 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -118,7 +118,7 @@
             return socket_loopback_server(port, SOCK_STREAM);
         }
     }
-#ifndef HAVE_WIN32_IPC  /* no Unix-domain sockets on Win32 */
+#if !defined(_WIN32)  // No Unix-domain sockets on Windows.
     // It's nonsensical to support the "reserved" space on the adb host side
     if (!strncmp(name, "local:", 6)) {
         return socket_local_server(name + 6, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 604bd57..4b97a14 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -63,6 +63,25 @@
   return result;
 }
 
+int mkdirs(const char *path)
+{
+    int ret;
+    char *x = (char *)path + 1;
+
+    for(;;) {
+        x = adb_dirstart(x);
+        if(x == 0) return 0;
+        *x = 0;
+        ret = adb_mkdir(path, 0775);
+        *x = OS_PATH_SEPARATOR;
+        if((ret < 0) && (errno != EEXIST)) {
+            return ret;
+        }
+        x++;
+    }
+    return 0;
+}
+
 void dump_hex(const void* data, size_t byte_count) {
     byte_count = std::min(byte_count, size_t(16));
 
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 84f7d0c..c816d00 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -22,6 +22,8 @@
 bool getcwd(std::string* cwd);
 bool directory_exists(const std::string& path);
 
+int mkdirs(const char *path);
+
 std::string escape_arg(const std::string& s);
 
 void dump_hex(const void* ptr, size_t byte_count);
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 4adac37..4e0db2b 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -724,25 +724,6 @@
     return send_shell_command(transport, serial, cmd);
 }
 
-static int mkdirs(const char *path)
-{
-    int ret;
-    char *x = (char *)path + 1;
-
-    for(;;) {
-        x = adb_dirstart(x);
-        if(x == 0) return 0;
-        *x = 0;
-        ret = adb_mkdir(path, 0775);
-        *x = OS_PATH_SEPARATOR;
-        if((ret < 0) && (errno != EEXIST)) {
-            return ret;
-        }
-        x++;
-    }
-    return 0;
-}
-
 static int backup(int argc, const char** argv) {
     const char* filename = "./backup.ab";
 
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 0c43c5e..5497613 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -42,7 +42,9 @@
 // This socket is used when a subproc shell service exists.
 // It wakes up the fdevent_loop() and cause the correct handling
 // of the shell's pseudo-tty master. I.e. force close it.
+#if !ADB_HOST
 int SHELL_EXIT_NOTIFY_FD = -1;
+#endif // !ADB_HOST
 
 static void fatal(const char *fn, const char *fmt, ...)
 {
@@ -81,7 +83,6 @@
 static void fdevent_plist_enqueue(fdevent *node);
 static void fdevent_plist_remove(fdevent *node);
 static fdevent *fdevent_plist_dequeue(void);
-static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
 
 static fdevent list_pending = {
     .next = &list_pending,
@@ -510,6 +511,7 @@
     fde->func(fde->fd, events, fde->arg);
 }
 
+#if !ADB_HOST
 static void fdevent_subproc_event_func(int fd, unsigned ev,
                                        void* /* userdata */)
 {
@@ -569,6 +571,24 @@
     }
 }
 
+void fdevent_subproc_setup()
+{
+    int s[2];
+
+    if(adb_socketpair(s)) {
+        FATAL("cannot create shell-exit socket-pair\n");
+    }
+    D("socketpair: (%d,%d)", s[0], s[1]);
+
+    SHELL_EXIT_NOTIFY_FD = s[0];
+    fdevent *fde;
+    fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
+    if(!fde)
+      FATAL("cannot create fdevent for shell-exit handler\n");
+    fdevent_add(fde, FDE_READ);
+}
+#endif // !ADB_HOST
+
 fdevent *fdevent_create(int fd, fd_func func, void *arg)
 {
     fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
@@ -661,27 +681,12 @@
         fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
 }
 
-void fdevent_subproc_setup()
-{
-    int s[2];
-
-    if(adb_socketpair(s)) {
-        FATAL("cannot create shell-exit socket-pair\n");
-    }
-    D("socketpair: (%d,%d)", s[0], s[1]);
-
-    SHELL_EXIT_NOTIFY_FD = s[0];
-    fdevent *fde;
-    fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
-    if(!fde)
-      FATAL("cannot create fdevent for shell-exit handler\n");
-    fdevent_add(fde, FDE_READ);
-}
-
 void fdevent_loop()
 {
     fdevent *fde;
+#if !ADB_HOST
     fdevent_subproc_setup();
+#endif // !ADB_HOST
 
     for(;;) {
         D("--- ---- waiting for events\n");
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 1dc711ae..49d42a3 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -32,6 +32,7 @@
 #include "adb.h"
 #include "adb_client.h"
 #include "adb_io.h"
+#include "adb_utils.h"
 #include "file_sync_service.h"
 
 static unsigned long long total_bytes;
@@ -395,25 +396,6 @@
     return -1;
 }
 
-static int mkdirs(const char *name)
-{
-    int ret;
-    char *x = (char *)name + 1;
-
-    for(;;) {
-        x = adb_dirstart(x);
-        if(x == 0) return 0;
-        *x = 0;
-        ret = adb_mkdir(name, 0775);
-        *x = OS_PATH_SEPARATOR;
-        if((ret < 0) && (errno != EEXIST)) {
-            return ret;
-        }
-        x++;
-    }
-    return 0;
-}
-
 static int sync_recv(int fd, const char* rpath, const char* lpath, int show_progress) {
     syncmsg msg;
     int len;
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index 3a4d2da..2893263 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -33,9 +33,12 @@
 #include "adb_io.h"
 #include "adb_utils.h"
 #include "cutils/properties.h"
+#include "fs_mgr.h"
+
+const std::string kFstab_Prefix = "/fstab.";
 
 // Returns the device used to mount a directory in /proc/mounts.
-static std::string find_mount(const char* dir) {
+static std::string find_proc_mount(const char* dir) {
     std::unique_ptr<FILE, int(*)(FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent);
     if (!fp) {
         return "";
@@ -50,6 +53,29 @@
     return "";
 }
 
+// Returns the device used to mount a directory in the fstab.
+static std::string find_fstab_mount(const char* dir) {
+    char propbuf[PROPERTY_VALUE_MAX];
+
+    property_get("ro.hardware", propbuf, "");
+    std::string fstab_filename = kFstab_Prefix + propbuf;
+    struct fstab* fstab = fs_mgr_read_fstab(fstab_filename.c_str());
+    struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, dir);
+    std::string dev = rec ? std::string(rec->blk_device) : "";
+    fs_mgr_free_fstab(fstab);
+    return dev;
+}
+
+// The proc entry for / is full of lies, so check fstab instead.
+// /proc/mounts lists rootfs and /dev/root, neither of which is what we want.
+static std::string find_mount(const char* dir) {
+    if (strcmp(dir, "/") == 0) {
+       return find_fstab_mount(dir);
+    } else {
+       return find_proc_mount(dir);
+    }
+}
+
 bool make_block_device_writable(const std::string& dev) {
     int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
     if (fd == -1) {
@@ -112,7 +138,13 @@
     }
 
     bool success = true;
-    success &= remount_partition(fd, "/system");
+    property_get("ro.build.system_root_image", prop_buf, "");
+    bool system_root = !strcmp(prop_buf, "true");
+    if (system_root) {
+        success &= remount_partition(fd, "/");
+    } else {
+        success &= remount_partition(fd, "/system");
+    }
     success &= remount_partition(fd, "/vendor");
     success &= remount_partition(fd, "/oem");
 
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 274449b..1bb130f 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -789,9 +789,10 @@
         if (result->connection_state == kCsUnauthorized) {
             *error_out = "device unauthorized.\n";
             char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
-            *error_out += "This adbd's $ADB_VENDOR_KEYS is ";
+            *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
             *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
-            *error_out += "; try 'adb kill-server' if that seems wrong.\n";
+            *error_out += "\n";
+            *error_out += "Try 'adb kill-server' if that seems wrong.\n";
             *error_out += "Otherwise check for a confirmation dialog on your device.";
             result = NULL;
         }
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 6cfb541..3fca709 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -77,12 +77,12 @@
 
 debuggerd_test_src_files := \
     utility.cpp \
-    test/dump_maps_test.cpp \
     test/dump_memory_test.cpp \
     test/elf_fake.cpp \
     test/log_fake.cpp \
     test/property_fake.cpp \
     test/ptrace_fake.cpp \
+    test/tombstone_test.cpp \
     test/selinux_fake.cpp \
 
 debuggerd_shared_libraries := \
diff --git a/debuggerd/arm/machine.cpp b/debuggerd/arm/machine.cpp
index b7d6997..78c2306 100644
--- a/debuggerd/arm/machine.cpp
+++ b/debuggerd/arm/machine.cpp
@@ -15,12 +15,15 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "DEBUG"
+
 #include <errno.h>
 #include <stdint.h>
 #include <string.h>
 #include <sys/ptrace.h>
 
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
@@ -28,7 +31,7 @@
 void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
   pt_regs regs;
   if (ptrace(PTRACE_GETREGS, backtrace->Tid(), 0, &regs)) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
@@ -48,7 +51,7 @@
 void dump_registers(log_t* log, pid_t tid) {
   pt_regs r;
   if (ptrace(PTRACE_GETREGS, tid, 0, &r)) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
@@ -68,7 +71,7 @@
 
   user_vfp vfp_regs;
   if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
-    _LOG(log, logtype::ERROR, "cannot get FP registers: %s\n", strerror(errno));
+    ALOGE("cannot get FP registers: %s\n", strerror(errno));
     return;
   }
 
diff --git a/debuggerd/arm64/machine.cpp b/debuggerd/arm64/machine.cpp
index 2e097da..e7bf79a 100644
--- a/debuggerd/arm64/machine.cpp
+++ b/debuggerd/arm64/machine.cpp
@@ -15,6 +15,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "DEBUG"
+
 #include <elf.h>
 #include <errno.h>
 #include <stdint.h>
@@ -23,6 +25,7 @@
 #include <sys/uio.h>
 
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
@@ -34,8 +37,7 @@
   io.iov_len = sizeof(regs);
 
   if (ptrace(PTRACE_GETREGSET, backtrace->Tid(), reinterpret_cast<void*>(NT_PRSTATUS), &io) == -1) {
-    _LOG(log, logtype::ERROR, "%s: ptrace failed to get registers: %s",
-         __func__, strerror(errno));
+    ALOGE("ptrace failed to get registers: %s", strerror(errno));
     return;
   }
 
@@ -57,7 +59,7 @@
   io.iov_len = sizeof(r);
 
   if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRSTATUS, (void*) &io) == -1) {
-    _LOG(log, logtype::ERROR, "ptrace error: %s\n", strerror(errno));
+    ALOGE("ptrace error: %s\n", strerror(errno));
     return;
   }
 
@@ -81,7 +83,7 @@
   io.iov_len = sizeof(f);
 
   if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRFPREG, (void*) &io) == -1) {
-    _LOG(log, logtype::ERROR, "ptrace error: %s\n", strerror(errno));
+    ALOGE("ptrace error: %s\n", strerror(errno));
     return;
   }
 
diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp
index b8084c5..b46f8f4 100644
--- a/debuggerd/backtrace.cpp
+++ b/debuggerd/backtrace.cpp
@@ -105,7 +105,7 @@
   }
 
   if (!attached && ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
-    _LOG(log, logtype::ERROR, "ptrace detach from %d failed: %s\n", tid, strerror(errno));
+    ALOGE("ptrace detach from %d failed: %s\n", tid, strerror(errno));
     *detach_failed = true;
   }
 }
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index deb4a9b..787b7aa 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -236,10 +236,7 @@
 
 static bool should_attach_gdb(debugger_request_t* request) {
   if (request->action == DEBUGGER_ACTION_CRASH) {
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.db.uid", value, "-1");
-    int debug_uid = atoi(value);
-    return debug_uid >= 0 && request->uid <= (uid_t)debug_uid;
+    return property_get_bool("debug.debuggerd.wait_for_gdb", false);
   }
   return false;
 }
diff --git a/debuggerd/mips/machine.cpp b/debuggerd/mips/machine.cpp
index f7b8a86..cbf272a 100644
--- a/debuggerd/mips/machine.cpp
+++ b/debuggerd/mips/machine.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "DEBUG"
+
 #include <errno.h>
 #include <inttypes.h>
 #include <stdint.h>
@@ -21,6 +23,7 @@
 #include <sys/ptrace.h>
 
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
@@ -32,7 +35,7 @@
 void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
   pt_regs r;
   if (ptrace(PTRACE_GETREGS, backtrace->Tid(), 0, &r)) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
@@ -61,7 +64,7 @@
 void dump_registers(log_t* log, pid_t tid) {
   pt_regs r;
   if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
diff --git a/debuggerd/mips64/machine.cpp b/debuggerd/mips64/machine.cpp
index 293dcf6..0a8d532 100644
--- a/debuggerd/mips64/machine.cpp
+++ b/debuggerd/mips64/machine.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "DEBUG"
+
 #include <errno.h>
 #include <inttypes.h>
 #include <stdint.h>
@@ -21,6 +23,7 @@
 #include <sys/ptrace.h>
 
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
@@ -32,7 +35,7 @@
 void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
   pt_regs r;
   if (ptrace(PTRACE_GETREGS, backtrace->Tid(), 0, &r)) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
@@ -61,7 +64,7 @@
 void dump_registers(log_t* log, pid_t tid) {
   pt_regs r;
   if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
diff --git a/debuggerd/test/BacktraceMock.h b/debuggerd/test/BacktraceMock.h
index 5c252ab..f75534e 100644
--- a/debuggerd/test/BacktraceMock.h
+++ b/debuggerd/test/BacktraceMock.h
@@ -60,12 +60,14 @@
     }
     size_t bytes_available = buffer_.size() - offset;
 
-    if (bytes_partial_read_ > 0) {
+    if (do_partial_read_) {
       // Do a partial read.
       if (bytes > bytes_partial_read_) {
         bytes = bytes_partial_read_;
       }
       bytes_partial_read_ -= bytes;
+      // Only support a single partial read.
+      do_partial_read_ = false;
     } else if (bytes > bytes_available) {
       bytes = bytes_available;
     }
@@ -82,6 +84,7 @@
     buffer_.resize(bytes);
     memcpy(buffer_.data(), buffer, bytes);
     bytes_partial_read_ = 0;
+    do_partial_read_ = false;
     last_read_addr_ = 0;
   }
 
@@ -90,12 +93,14 @@
       abort();
     }
     bytes_partial_read_ = bytes;
+    do_partial_read_ = true;
   }
 
  private:
   std::vector<uint8_t> buffer_;
   size_t bytes_partial_read_ = 0;
   uintptr_t last_read_addr_ = 0;
+  bool do_partial_read_ = false;
 };
 
 #endif //  _DEBUGGERD_TEST_BACKTRACE_MOCK_H
diff --git a/debuggerd/test/dump_memory_test.cpp b/debuggerd/test/dump_memory_test.cpp
index fcb0108..75e7028 100644
--- a/debuggerd/test/dump_memory_test.cpp
+++ b/debuggerd/test/dump_memory_test.cpp
@@ -288,9 +288,9 @@
   ASSERT_STREQ(g_expected_partial_dump, tombstone_contents.c_str());
 
 #if defined(__LP64__)
-  ASSERT_STREQ("DEBUG Bytes read 102, is not a multiple of 8\n", getFakeLogPrint().c_str());
+  ASSERT_STREQ("6 DEBUG Bytes read 102, is not a multiple of 8\n", getFakeLogPrint().c_str());
 #else
-  ASSERT_STREQ("DEBUG Bytes read 102, is not a multiple of 4\n", getFakeLogPrint().c_str());
+  ASSERT_STREQ("6 DEBUG Bytes read 102, is not a multiple of 4\n", getFakeLogPrint().c_str());
 #endif
 
   // Verify that the log buf is empty, and no error messages.
@@ -313,12 +313,12 @@
   ASSERT_STREQ(g_expected_partial_dump, tombstone_contents.c_str());
 
 #if defined(__LP64__)
-  ASSERT_STREQ("DEBUG Bytes read 45, is not a multiple of 8\n"
-               "DEBUG Bytes after second read 106, is not a multiple of 8\n",
+  ASSERT_STREQ("6 DEBUG Bytes read 45, is not a multiple of 8\n"
+               "6 DEBUG Bytes after second read 106, is not a multiple of 8\n",
                getFakeLogPrint().c_str());
 #else
-  ASSERT_STREQ("DEBUG Bytes read 45, is not a multiple of 4\n"
-               "DEBUG Bytes after second read 106, is not a multiple of 4\n",
+  ASSERT_STREQ("6 DEBUG Bytes read 45, is not a multiple of 4\n"
+               "6 DEBUG Bytes after second read 106, is not a multiple of 4\n",
                getFakeLogPrint().c_str());
 #endif
 
@@ -502,3 +502,239 @@
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
+
+TEST_F(DumpMemoryTest, first_read_empty) {
+  uint8_t buffer[256];
+  for (size_t i = 0; i < sizeof(buffer); i++) {
+    buffer[i] = i;
+  }
+  backtrace_mock_->SetReadData(buffer, sizeof(buffer));
+  backtrace_mock_->SetPartialReadAmount(0);
+
+  size_t page_size = sysconf(_SC_PAGE_SIZE);
+  uintptr_t addr = 0x10000020 + page_size - 120;
+  dump_memory(&log_, backtrace_mock_.get(), addr, "memory near %.2s:", "r4");
+
+  std::string tombstone_contents;
+  ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
+  ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
+  const char* expected_dump = \
+"\nmemory near r4:\n"
+#if defined(__LP64__)
+"    0000000010000f88 ---------------- ----------------  ................\n"
+"    0000000010000f98 ---------------- ----------------  ................\n"
+"    0000000010000fa8 ---------------- ----------------  ................\n"
+"    0000000010000fb8 ---------------- ----------------  ................\n"
+"    0000000010000fc8 ---------------- ----------------  ................\n"
+"    0000000010000fd8 ---------------- ----------------  ................\n"
+"    0000000010000fe8 ---------------- ----------------  ................\n"
+"    0000000010000ff8 ---------------- 7f7e7d7c7b7a7978  ........xyz{|}~.\n"
+"    0000000010001008 8786858483828180 8f8e8d8c8b8a8988  ................\n"
+"    0000000010001018 9796959493929190 9f9e9d9c9b9a9998  ................\n"
+"    0000000010001028 a7a6a5a4a3a2a1a0 afaeadacabaaa9a8  ................\n"
+"    0000000010001038 b7b6b5b4b3b2b1b0 bfbebdbcbbbab9b8  ................\n"
+"    0000000010001048 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8  ................\n"
+"    0000000010001058 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8  ................\n"
+"    0000000010001068 e7e6e5e4e3e2e1e0 efeeedecebeae9e8  ................\n"
+"    0000000010001078 f7f6f5f4f3f2f1f0 fffefdfcfbfaf9f8  ................\n";
+#else
+"    10000f88 -------- -------- -------- --------  ................\n"
+"    10000f98 -------- -------- -------- --------  ................\n"
+"    10000fa8 -------- -------- -------- --------  ................\n"
+"    10000fb8 -------- -------- -------- --------  ................\n"
+"    10000fc8 -------- -------- -------- --------  ................\n"
+"    10000fd8 -------- -------- -------- --------  ................\n"
+"    10000fe8 -------- -------- -------- --------  ................\n"
+"    10000ff8 -------- -------- 7b7a7978 7f7e7d7c  ........xyz{|}~.\n"
+"    10001008 83828180 87868584 8b8a8988 8f8e8d8c  ................\n"
+"    10001018 93929190 97969594 9b9a9998 9f9e9d9c  ................\n"
+"    10001028 a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac  ................\n"
+"    10001038 b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc  ................\n"
+"    10001048 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc  ................\n"
+"    10001058 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc  ................\n"
+"    10001068 e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec  ................\n"
+"    10001078 f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc  ................\n";
+#endif
+  ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+
+  // Verify that the log buf is empty, and no error messages.
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(DumpMemoryTest, first_read_empty_second_read_stops) {
+  uint8_t buffer[224];
+  for (size_t i = 0; i < sizeof(buffer); i++) {
+    buffer[i] = i;
+  }
+  backtrace_mock_->SetReadData(buffer, sizeof(buffer));
+  backtrace_mock_->SetPartialReadAmount(0);
+
+  size_t page_size = sysconf(_SC_PAGE_SIZE);
+  uintptr_t addr = 0x10000020 + page_size - 192;
+  dump_memory(&log_, backtrace_mock_.get(), addr, "memory near %.2s:", "r4");
+
+  std::string tombstone_contents;
+  ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
+  ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
+  const char* expected_dump = \
+"\nmemory near r4:\n"
+#if defined(__LP64__)
+"    0000000010000f40 ---------------- ----------------  ................\n"
+"    0000000010000f50 ---------------- ----------------  ................\n"
+"    0000000010000f60 ---------------- ----------------  ................\n"
+"    0000000010000f70 ---------------- ----------------  ................\n"
+"    0000000010000f80 ---------------- ----------------  ................\n"
+"    0000000010000f90 ---------------- ----------------  ................\n"
+"    0000000010000fa0 ---------------- ----------------  ................\n"
+"    0000000010000fb0 ---------------- ----------------  ................\n"
+"    0000000010000fc0 ---------------- ----------------  ................\n"
+"    0000000010000fd0 ---------------- ----------------  ................\n"
+"    0000000010000fe0 ---------------- ----------------  ................\n"
+"    0000000010000ff0 ---------------- ----------------  ................\n"
+"    0000000010001000 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8  ................\n"
+"    0000000010001010 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8  ................\n"
+"    0000000010001020 ---------------- ----------------  ................\n"
+"    0000000010001030 ---------------- ----------------  ................\n";
+#else
+"    10000f40 -------- -------- -------- --------  ................\n"
+"    10000f50 -------- -------- -------- --------  ................\n"
+"    10000f60 -------- -------- -------- --------  ................\n"
+"    10000f70 -------- -------- -------- --------  ................\n"
+"    10000f80 -------- -------- -------- --------  ................\n"
+"    10000f90 -------- -------- -------- --------  ................\n"
+"    10000fa0 -------- -------- -------- --------  ................\n"
+"    10000fb0 -------- -------- -------- --------  ................\n"
+"    10000fc0 -------- -------- -------- --------  ................\n"
+"    10000fd0 -------- -------- -------- --------  ................\n"
+"    10000fe0 -------- -------- -------- --------  ................\n"
+"    10000ff0 -------- -------- -------- --------  ................\n"
+"    10001000 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc  ................\n"
+"    10001010 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc  ................\n"
+"    10001020 -------- -------- -------- --------  ................\n"
+"    10001030 -------- -------- -------- --------  ................\n";
+#endif
+  ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+
+  // Verify that the log buf is empty, and no error messages.
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(DumpMemoryTest, first_read_empty_next_page_out_of_range) {
+  uint8_t buffer[256];
+  for (size_t i = 0; i < sizeof(buffer); i++) {
+    buffer[i] = i;
+  }
+  backtrace_mock_->SetReadData(buffer, sizeof(buffer));
+  backtrace_mock_->SetPartialReadAmount(0);
+
+  uintptr_t addr = 0x10000020;
+  dump_memory(&log_, backtrace_mock_.get(), addr, "memory near %.2s:", "r4");
+
+  std::string tombstone_contents;
+  ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
+  ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
+  const char* expected_dump = \
+"\nmemory near r4:\n"
+#if defined(__LP64__)
+"    0000000010000000 ---------------- ----------------  ................\n"
+"    0000000010000010 ---------------- ----------------  ................\n"
+"    0000000010000020 ---------------- ----------------  ................\n"
+"    0000000010000030 ---------------- ----------------  ................\n"
+"    0000000010000040 ---------------- ----------------  ................\n"
+"    0000000010000050 ---------------- ----------------  ................\n"
+"    0000000010000060 ---------------- ----------------  ................\n"
+"    0000000010000070 ---------------- ----------------  ................\n"
+"    0000000010000080 ---------------- ----------------  ................\n"
+"    0000000010000090 ---------------- ----------------  ................\n"
+"    00000000100000a0 ---------------- ----------------  ................\n"
+"    00000000100000b0 ---------------- ----------------  ................\n"
+"    00000000100000c0 ---------------- ----------------  ................\n"
+"    00000000100000d0 ---------------- ----------------  ................\n"
+"    00000000100000e0 ---------------- ----------------  ................\n"
+"    00000000100000f0 ---------------- ----------------  ................\n";
+#else
+"    10000000 -------- -------- -------- --------  ................\n"
+"    10000010 -------- -------- -------- --------  ................\n"
+"    10000020 -------- -------- -------- --------  ................\n"
+"    10000030 -------- -------- -------- --------  ................\n"
+"    10000040 -------- -------- -------- --------  ................\n"
+"    10000050 -------- -------- -------- --------  ................\n"
+"    10000060 -------- -------- -------- --------  ................\n"
+"    10000070 -------- -------- -------- --------  ................\n"
+"    10000080 -------- -------- -------- --------  ................\n"
+"    10000090 -------- -------- -------- --------  ................\n"
+"    100000a0 -------- -------- -------- --------  ................\n"
+"    100000b0 -------- -------- -------- --------  ................\n"
+"    100000c0 -------- -------- -------- --------  ................\n"
+"    100000d0 -------- -------- -------- --------  ................\n"
+"    100000e0 -------- -------- -------- --------  ................\n"
+"    100000f0 -------- -------- -------- --------  ................\n";
+#endif
+  ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+
+  // Verify that the log buf is empty, and no error messages.
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(DumpMemoryTest, first_read_empty_next_page_out_of_range_fence_post) {
+  uint8_t buffer[256];
+  for (size_t i = 0; i < sizeof(buffer); i++) {
+    buffer[i] = i;
+  }
+  backtrace_mock_->SetReadData(buffer, sizeof(buffer));
+  backtrace_mock_->SetPartialReadAmount(0);
+
+  size_t page_size = sysconf(_SC_PAGE_SIZE);
+  uintptr_t addr = 0x10000020 + page_size - 256;
+
+  dump_memory(&log_, backtrace_mock_.get(), addr, "memory near %.2s:", "r4");
+
+  std::string tombstone_contents;
+  ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
+  ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
+  const char* expected_dump = \
+"\nmemory near r4:\n"
+#if defined(__LP64__)
+"    0000000010000f00 ---------------- ----------------  ................\n"
+"    0000000010000f10 ---------------- ----------------  ................\n"
+"    0000000010000f20 ---------------- ----------------  ................\n"
+"    0000000010000f30 ---------------- ----------------  ................\n"
+"    0000000010000f40 ---------------- ----------------  ................\n"
+"    0000000010000f50 ---------------- ----------------  ................\n"
+"    0000000010000f60 ---------------- ----------------  ................\n"
+"    0000000010000f70 ---------------- ----------------  ................\n"
+"    0000000010000f80 ---------------- ----------------  ................\n"
+"    0000000010000f90 ---------------- ----------------  ................\n"
+"    0000000010000fa0 ---------------- ----------------  ................\n"
+"    0000000010000fb0 ---------------- ----------------  ................\n"
+"    0000000010000fc0 ---------------- ----------------  ................\n"
+"    0000000010000fd0 ---------------- ----------------  ................\n"
+"    0000000010000fe0 ---------------- ----------------  ................\n"
+"    0000000010000ff0 ---------------- ----------------  ................\n";
+#else
+"    10000f00 -------- -------- -------- --------  ................\n"
+"    10000f10 -------- -------- -------- --------  ................\n"
+"    10000f20 -------- -------- -------- --------  ................\n"
+"    10000f30 -------- -------- -------- --------  ................\n"
+"    10000f40 -------- -------- -------- --------  ................\n"
+"    10000f50 -------- -------- -------- --------  ................\n"
+"    10000f60 -------- -------- -------- --------  ................\n"
+"    10000f70 -------- -------- -------- --------  ................\n"
+"    10000f80 -------- -------- -------- --------  ................\n"
+"    10000f90 -------- -------- -------- --------  ................\n"
+"    10000fa0 -------- -------- -------- --------  ................\n"
+"    10000fb0 -------- -------- -------- --------  ................\n"
+"    10000fc0 -------- -------- -------- --------  ................\n"
+"    10000fd0 -------- -------- -------- --------  ................\n"
+"    10000fe0 -------- -------- -------- --------  ................\n"
+"    10000ff0 -------- -------- -------- --------  ................\n";
+#endif
+  ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+
+  // Verify that the log buf is empty, and no error messages.
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
diff --git a/debuggerd/test/log_fake.cpp b/debuggerd/test/log_fake.cpp
index 26523ad..d584a5e 100644
--- a/debuggerd/test/log_fake.cpp
+++ b/debuggerd/test/log_fake.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <errno.h>
 #include <stdarg.h>
 
 #include <string>
@@ -44,14 +45,16 @@
   return g_fake_log_print;
 }
 
-extern "C" int __android_log_buf_write(int, int, const char* tag, const char* msg) {
+extern "C" int __android_log_buf_write(int bufId, int prio, const char* tag, const char* msg) {
+  g_fake_log_buf += std::to_string(bufId) + ' ' + std::to_string(prio) + ' ';
   g_fake_log_buf += tag;
   g_fake_log_buf += ' ';
   g_fake_log_buf += msg;
   return 1;
 }
 
-extern "C" int __android_log_print(int, const char* tag, const char* fmt, ...) {
+extern "C" int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
+  g_fake_log_print += std::to_string(prio) + ' ';
   g_fake_log_print += tag;
   g_fake_log_print += ' ';
 
@@ -70,6 +73,7 @@
 }
 
 extern "C" struct logger_list* android_logger_list_open(log_id_t, int, unsigned int, pid_t) {
+  errno = EACCES;
   return nullptr;
 }
 
diff --git a/debuggerd/test/dump_maps_test.cpp b/debuggerd/test/tombstone_test.cpp
similarity index 90%
rename from debuggerd/test/dump_maps_test.cpp
rename to debuggerd/test/tombstone_test.cpp
index 230f4f5..a771a39 100644
--- a/debuggerd/test/dump_maps_test.cpp
+++ b/debuggerd/test/tombstone_test.cpp
@@ -45,7 +45,7 @@
 void dump_backtrace_to_log(Backtrace*, log_t*, char const*) {
 }
 
-class DumpMapsTest : public ::testing::Test {
+class TombstoneTest : public ::testing::Test {
  protected:
   virtual void SetUp() {
     map_mock_.reset(new BacktraceMapMock());
@@ -92,7 +92,7 @@
   log_t log_;
 };
 
-TEST_F(DumpMapsTest, single_map) {
+TEST_F(TombstoneTest, single_map) {
   backtrace_map_t map;
 #if defined(__LP64__)
   map.start = 0x123456789abcd000UL;
@@ -122,7 +122,7 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
-TEST_F(DumpMapsTest, single_map_elf_build_id) {
+TEST_F(TombstoneTest, single_map_elf_build_id) {
   backtrace_map_t map;
 #if defined(__LP64__)
   map.start = 0x123456789abcd000UL;
@@ -157,7 +157,7 @@
 
 // Even though build id is present, it should not be printed in either of
 // these cases.
-TEST_F(DumpMapsTest, single_map_no_build_id) {
+TEST_F(TombstoneTest, single_map_no_build_id) {
   backtrace_map_t map;
 #if defined(__LP64__)
   map.start = 0x123456789abcd000UL;
@@ -194,7 +194,7 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
-TEST_F(DumpMapsTest, multiple_maps) {
+TEST_F(TombstoneTest, multiple_maps) {
   backtrace_map_t map;
 
   map.start = 0xa234000;
@@ -256,7 +256,7 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
-TEST_F(DumpMapsTest, multiple_maps_fault_address_before) {
+TEST_F(TombstoneTest, multiple_maps_fault_address_before) {
   backtrace_map_t map;
 
   map.start = 0xa434000;
@@ -310,7 +310,7 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
-TEST_F(DumpMapsTest, multiple_maps_fault_address_between) {
+TEST_F(TombstoneTest, multiple_maps_fault_address_between) {
   backtrace_map_t map;
 
   map.start = 0xa434000;
@@ -364,7 +364,7 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
-TEST_F(DumpMapsTest, multiple_maps_fault_address_in_map) {
+TEST_F(TombstoneTest, multiple_maps_fault_address_in_map) {
   backtrace_map_t map;
 
   map.start = 0xa434000;
@@ -416,7 +416,7 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
-TEST_F(DumpMapsTest, multiple_maps_fault_address_after) {
+TEST_F(TombstoneTest, multiple_maps_fault_address_after) {
   backtrace_map_t map;
 
   map.start = 0xa434000;
@@ -474,7 +474,7 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
-TEST_F(DumpMapsTest, multiple_maps_getsiginfo_fail) {
+TEST_F(TombstoneTest, multiple_maps_getsiginfo_fail) {
   backtrace_map_t map;
 
   map.start = 0xa434000;
@@ -493,7 +493,6 @@
   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
   const char* expected_dump = \
-"Cannot get siginfo for 100: Bad address\n"
 "\nmemory map:\n"
 #if defined(__LP64__)
 "    00000000'0a434000-00000000'0a434fff -w-      1000      1000  (load base 0xd000)\n";
@@ -503,12 +502,11 @@
   ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
 
   // Verify that the log buf is empty, and no error messages.
-  ASSERT_STREQ("DEBUG Cannot get siginfo for 100: Bad address\n",
-               getFakeLogBuf().c_str());
-  ASSERT_STREQ("", getFakeLogPrint().c_str());
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("6 DEBUG Cannot get siginfo for 100: Bad address\n\n", getFakeLogPrint().c_str());
 }
 
-TEST_F(DumpMapsTest, multiple_maps_check_signal_has_si_addr) {
+TEST_F(TombstoneTest, multiple_maps_check_signal_has_si_addr) {
   backtrace_map_t map;
 
   map.start = 0xa434000;
@@ -569,3 +567,33 @@
     ASSERT_STREQ("", getFakeLogPrint().c_str());
   }
 }
+
+TEST_F(TombstoneTest, dump_signal_info_error) {
+  siginfo_t si;
+  si.si_signo = 0;
+  ptrace_set_fake_getsiginfo(si);
+
+  dump_signal_info(&log_, 123, SIGSEGV, 10);
+
+  std::string tombstone_contents;
+  ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
+  ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
+  ASSERT_STREQ("", tombstone_contents.c_str());
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("6 DEBUG cannot get siginfo: Bad address\n\n", getFakeLogPrint().c_str());
+}
+
+TEST_F(TombstoneTest, dump_log_file_error) {
+  log_.should_retrieve_logcat = true;
+  dump_log_file(&log_, 123, "/fake/filename", 10);
+
+  std::string tombstone_contents;
+  ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
+  ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
+  ASSERT_STREQ("", tombstone_contents.c_str());
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("6 DEBUG Unable to open /fake/filename: Permission denied\n\n",
+               getFakeLogPrint().c_str());
+}
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index b0ad274..114c7e4 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -180,7 +180,7 @@
   siginfo_t si;
   memset(&si, 0, sizeof(si));
   if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si) == -1) {
-    _LOG(log, logtype::HEADER, "cannot get siginfo: %s\n", strerror(errno));
+    ALOGE("cannot get siginfo: %s\n", strerror(errno));
     return;
   }
 
@@ -338,7 +338,7 @@
     print_fault_address_marker = signal_has_si_addr(si.si_signo);
     addr = reinterpret_cast<uintptr_t>(si.si_addr);
   } else {
-    _LOG(log, logtype::ERROR, "Cannot get siginfo for %d: %s\n", tid, strerror(errno));
+    ALOGE("Cannot get siginfo for %d: %s\n", tid, strerror(errno));
   }
 
   _LOG(log, logtype::MAPS, "\n");
@@ -448,7 +448,7 @@
 
     // Skip this thread if cannot ptrace it
     if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) {
-      _LOG(log, logtype::ERROR, "ptrace attach to %d failed: %s\n", new_tid, strerror(errno));
+      ALOGE("ptrace attach to %d failed: %s\n", new_tid, strerror(errno));
       continue;
     }
 
@@ -471,7 +471,7 @@
     log->current_tid = log->crashed_tid;
 
     if (ptrace(PTRACE_DETACH, new_tid, 0, 0) != 0) {
-      _LOG(log, logtype::ERROR, "ptrace detach from %d failed: %s\n", new_tid, strerror(errno));
+      ALOGE("ptrace detach from %d failed: %s\n", new_tid, strerror(errno));
       detach_failed = true;
     }
   }
@@ -517,13 +517,11 @@
         // non-blocking EOF; we're done
         break;
       } else {
-        _LOG(log, logtype::ERROR, "Error while reading log: %s\n",
-          strerror(-actual));
+        ALOGE("Error while reading log: %s\n", strerror(-actual));
         break;
       }
     } else if (actual == 0) {
-      _LOG(log, logtype::ERROR, "Got zero bytes while reading log: %s\n",
-        strerror(errno));
+      ALOGE("Got zero bytes while reading log: %s\n", strerror(errno));
       break;
     }
 
@@ -789,11 +787,11 @@
   log.crashed_tid = tid;
 
   if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) {
-    _LOG(&log, logtype::ERROR, "failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno));
+    ALOGE("failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno));
   }
 
   if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) {
-    _LOG(&log, logtype::ERROR, "failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno));
+    ALOGE("failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno));
   }
 
   int fd = -1;
@@ -801,11 +799,11 @@
   if (selinux_android_restorecon(TOMBSTONE_DIR, 0) == 0) {
     path = find_and_open_tombstone(&fd);
   } else {
-    _LOG(&log, logtype::ERROR, "Failed to restore security context, not writing tombstone.\n");
+    ALOGE("Failed to restore security context, not writing tombstone.\n");
   }
 
   if (fd < 0) {
-    _LOG(&log, logtype::ERROR, "Skipping tombstone write, nothing to do.\n");
+    ALOGE("Skipping tombstone write, nothing to do.\n");
     *detach_failed = false;
     return NULL;
   }
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index 9f340a8..f5d6ec1 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -35,8 +35,7 @@
 
 // Whitelist output desired in the logcat output.
 bool is_allowed_in_logcat(enum logtype ltype) {
-  if ((ltype == ERROR)
-   || (ltype == HEADER)
+  if ((ltype == HEADER)
    || (ltype == REGISTERS)
    || (ltype == BACKTRACE)) {
     return true;
@@ -157,13 +156,28 @@
     bytes &= ~(sizeof(uintptr_t) - 1);
   }
 
-  if (bytes < MEMORY_BYTES_TO_DUMP && bytes > 0) {
-    // Try to do one more read. This could happen if a read crosses a map, but
-    // the maps do not have any break between them. Only requires one extra
-    // read because a map has to contain at least one page, and the total
-    // number of bytes to dump is smaller than a page.
-    size_t bytes2 = backtrace->Read(addr + bytes, reinterpret_cast<uint8_t*>(data) + bytes,
-                                    sizeof(data) - bytes);
+  uintptr_t start = 0;
+  bool skip_2nd_read = false;
+  if (bytes == 0) {
+    // In this case, we might want to try another read at the beginning of
+    // the next page only if it's within the amount of memory we would have
+    // read.
+    size_t page_size = sysconf(_SC_PAGE_SIZE);
+    start = ((addr + (page_size - 1)) & ~(page_size - 1)) - addr;
+    if (start == 0 || start >= MEMORY_BYTES_TO_DUMP) {
+      skip_2nd_read = true;
+    }
+  }
+
+  if (bytes < MEMORY_BYTES_TO_DUMP && !skip_2nd_read) {
+    // Try to do one more read. This could happen if a read crosses a map,
+    // but the maps do not have any break between them. Or it could happen
+    // if reading from an unreadable map, but the read would cross back
+    // into a readable map. Only requires one extra read because a map has
+    // to contain at least one page, and the total number of bytes to dump
+    // is smaller than a page.
+    size_t bytes2 = backtrace->Read(addr + start + bytes, reinterpret_cast<uint8_t*>(data) + bytes,
+                                    sizeof(data) - bytes - start);
     bytes += bytes2;
     if (bytes2 > 0 && bytes % sizeof(uintptr_t) != 0) {
       // This should never happen, but we'll try and continue any way.
@@ -179,15 +193,16 @@
   // On 32-bit machines, there are still 16 bytes per line but addresses and
   // words are of course presented differently.
   uintptr_t* data_ptr = data;
+  size_t current = 0;
+  size_t total_bytes = start + bytes;
   for (size_t line = 0; line < MEMORY_BYTES_TO_DUMP / MEMORY_BYTES_PER_LINE; line++) {
     std::string logline;
     android::base::StringAppendF(&logline, "    %" PRIPTR, addr);
 
     addr += MEMORY_BYTES_PER_LINE;
     std::string ascii;
-    for (size_t i = 0; i < MEMORY_BYTES_PER_LINE / sizeof(uintptr_t); i++, data_ptr++) {
-      if (bytes >= sizeof(uintptr_t)) {
-        bytes -= sizeof(uintptr_t);
+    for (size_t i = 0; i < MEMORY_BYTES_PER_LINE / sizeof(uintptr_t); i++) {
+      if (current >= start && current + sizeof(uintptr_t) <= total_bytes) {
         android::base::StringAppendF(&logline, " %" PRIPTR, *data_ptr);
 
         // Fill out the ascii string from the data.
@@ -199,10 +214,12 @@
             ascii += '.';
           }
         }
+        data_ptr++;
       } else {
         logline += ' ' + std::string(sizeof(uintptr_t) * 2, '-');
         ascii += std::string(sizeof(uintptr_t), '.');
       }
+      current += sizeof(uintptr_t);
     }
     _LOG(log, logtype::MEMORY, "%s  %s\n", logline.c_str(), ascii.c_str());
   }
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 263374d..8bef192 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -59,7 +59,6 @@
 
 // List of types of logs to simplify the logging decision in _LOG
 enum logtype {
-  ERROR,
   HEADER,
   THREAD,
   REGISTERS,
diff --git a/debuggerd/x86/machine.cpp b/debuggerd/x86/machine.cpp
index c5f9259..af10817 100644
--- a/debuggerd/x86/machine.cpp
+++ b/debuggerd/x86/machine.cpp
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "DEBUG"
+
 #include <errno.h>
 #include <stdint.h>
 #include <string.h>
 #include <sys/ptrace.h>
 
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
@@ -27,7 +30,7 @@
 void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
   struct pt_regs r;
   if (ptrace(PTRACE_GETREGS, backtrace->Tid(), 0, &r) == -1) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
@@ -44,7 +47,7 @@
 void dump_registers(log_t* log, pid_t tid) {
   struct pt_regs r;
   if (ptrace(PTRACE_GETREGS, tid, 0, &r) == -1) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
diff --git a/debuggerd/x86_64/machine.cpp b/debuggerd/x86_64/machine.cpp
index 4f09a5d..fc86bc2 100644
--- a/debuggerd/x86_64/machine.cpp
+++ b/debuggerd/x86_64/machine.cpp
@@ -14,6 +14,8 @@
 ** limitations under the License.
 */
 
+#define LOG_TAG "DEBUG"
+
 #include <errno.h>
 #include <stdint.h>
 #include <sys/ptrace.h>
@@ -21,6 +23,7 @@
 #include <sys/user.h>
 
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
@@ -28,7 +31,7 @@
 void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
   struct user_regs_struct r;
   if (ptrace(PTRACE_GETREGS, backtrace->Tid(), 0, &r) == -1) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
@@ -45,7 +48,7 @@
 void dump_registers(log_t* log, pid_t tid) {
   struct user_regs_struct r;
   if (ptrace(PTRACE_GETREGS, tid, 0, &r) == -1) {
-    _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+    ALOGE("cannot get registers: %s\n", strerror(errno));
     return;
   }
 
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index 0a945a3..a4a99c3 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -859,6 +859,7 @@
 int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
 {
     _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE];
+    bool use_state = true;
     char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
     char *mount_point;
     char propbuf[PROPERTY_VALUE_MAX];
@@ -875,7 +876,10 @@
     property_get("ro.boot.veritymode", propbuf, "");
 
     if (*propbuf != '\0') {
-        return 0; /* state is kept by the bootloader */
+        if (fs_mgr_load_verity_state(&mode) == -1) {
+            return -1;
+        }
+        use_state = false; /* state is kept by the bootloader */
     }
 
     fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
@@ -900,9 +904,11 @@
             continue;
         }
 
-        if (get_verity_state_offset(&fstab->recs[i], &offset) < 0 ||
-            read_verity_state(fstab->recs[i].verity_loc, offset, &mode) < 0) {
-            continue;
+        if (use_state) {
+            if (get_verity_state_offset(&fstab->recs[i], &offset) < 0 ||
+                read_verity_state(fstab->recs[i].verity_loc, offset, &mode) < 0) {
+                continue;
+            }
         }
 
         mount_point = basename(fstab->recs[i].mount_point);
@@ -916,7 +922,7 @@
 
         status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
 
-        if (*status == 'C') {
+        if (use_state && *status == 'C') {
             if (write_verity_state(fstab->recs[i].verity_loc, offset,
                     VERITY_MODE_LOGGING) < 0) {
                 continue;
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 02fe2b5..0c071ca 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -77,6 +77,7 @@
 #define AID_SDCARD_ALL    1035  /* access all users external storage */
 #define AID_LOGD          1036  /* log daemon */
 #define AID_SHARED_RELRO  1037  /* creator of shared GNU RELRO files */
+#define AID_DBUS          1038  /* dbus-daemon IPC broker process */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
 #define AID_CACHE         2001  /* cache access */
@@ -168,6 +169,7 @@
     { "sdcard_all",    AID_SDCARD_ALL, },
     { "logd",          AID_LOGD, },
     { "shared_relro",  AID_SHARED_RELRO, },
+    { "dbus",          AID_DBUS, },
 
     { "shell",         AID_SHELL, },
     { "cache",         AID_CACHE, },
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index 95687cb..81b20fa 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -164,10 +164,11 @@
         // timeout. this is useful when using -wipe-data since the /data
         // partition is fresh.
         std::string cmdline;
+        const char* s;
         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);
+        if ((s = strstr(cmdline.c_str(), KERNEL_OPTION)) != NULL) {
+            timeout = atoi(s + sizeof(KERNEL_OPTION) - 1);
         }
     }
     if (timeout == 0)
diff --git a/init/init.cpp b/init/init.cpp
index f48016f..4d62c87 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -239,16 +239,20 @@
         rc = getfilecon(svc->args[0], &fcon);
         if (rc < 0) {
             ERROR("could not get context while starting '%s'\n", svc->name);
-            freecon(mycon);
+            free(mycon);
             return;
         }
 
         rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
         if (rc == 0 && !strcmp(scon, mycon)) {
-            ERROR("Warning!  Service %s needs a SELinux domain defined; please fix!\n", svc->name);
+            ERROR("Service %s does not have a SELinux domain defined.\n", svc->name);
+            free(mycon);
+            free(fcon);
+            free(scon);
+            return;
         }
-        freecon(mycon);
-        freecon(fcon);
+        free(mycon);
+        free(fcon);
         if (rc < 0) {
             ERROR("could not get context while starting '%s'\n", svc->name);
             return;
@@ -285,7 +289,7 @@
             }
         }
 
-        freecon(scon);
+        free(scon);
         scon = NULL;
 
         if (svc->writepid_files_) {
@@ -374,7 +378,7 @@
         _exit(127);
     }
 
-    freecon(scon);
+    free(scon);
 
     if (pid < 0) {
         ERROR("failed to start '%s'\n", svc->name);
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 760f5cc..6bd7529 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -974,8 +974,8 @@
           << "Offset at " << i << " length " << j << " wrote too much data";
     }
   }
-  delete data;
-  delete expected;
+  delete[] data;
+  delete[] expected;
 }
 
 TEST(libbacktrace, thread_read) {
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 9f8023e..cb77ee6 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -76,6 +76,7 @@
 
 static const struct fs_path_config android_dirs[] = {
     { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },
+    { 00500, AID_ROOT,   AID_ROOT,   0, "config" },
     { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
     { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
     { 00771, AID_ROOT,   AID_ROOT,   0, "data/dalvik-cache" },
@@ -88,7 +89,10 @@
     { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
     { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
     { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
+    { 00755, AID_ROOT,   AID_SYSTEM, 0, "mnt" },
+    { 00755, AID_ROOT,   AID_ROOT,   0, "root" },
     { 00750, AID_ROOT,   AID_SHELL,  0, "sbin" },
+    { 00751, AID_ROOT,   AID_SDCARD_R, 0, "storage" },
     { 00755, AID_ROOT,   AID_SHELL,  0, "system/bin" },
     { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },
     { 00755, AID_ROOT,   AID_SHELL,  0, "system/xbin" },
diff --git a/libcutils/socket_network_client.c b/libcutils/socket_network_client.c
index e0031ba..2610254 100644
--- a/libcutils/socket_network_client.c
+++ b/libcutils/socket_network_client.c
@@ -29,77 +29,74 @@
 
 #include <cutils/sockets.h>
 
-/* Connect to port on the IP interface. type is
- * SOCK_STREAM or SOCK_DGRAM. 
- * return is a file descriptor or -1 on error
- */
-int socket_network_client(const char *host, int port, int type)
-{
-    return socket_network_client_timeout(host, port, type, 0);
+static int toggle_O_NONBLOCK(int s) {
+    int flags = fcntl(s, F_GETFL);
+    if (flags == -1 || fcntl(s, F_SETFL, flags ^ O_NONBLOCK) == -1) {
+        close(s);
+        return -1;
+    }
+    return s;
 }
 
-/* Connect to port on the IP interface. type is SOCK_STREAM or SOCK_DGRAM.
- * timeout in seconds return is a file descriptor or -1 on error
- */
-int socket_network_client_timeout(const char *host, int port, int type, int timeout)
-{
-    struct hostent *hp;
-    struct sockaddr_in addr;
-    int s;
-    int flags = 0, error = 0, ret = 0;
-    fd_set rset, wset;
-    socklen_t len = sizeof(error);
-    struct timeval ts;
+// Connect to the given host and port.
+// 'timeout' is in seconds (0 for no timeout).
+// Returns a file descriptor or -1 on error.
+int socket_network_client_timeout(const char* host, int port, int type, int timeout) {
+    struct addrinfo hints;
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = type;
 
+    char port_str[16];
+    snprintf(port_str, sizeof(port_str), "%d", port);
+
+    struct addrinfo* addrs;
+    if (getaddrinfo(host, port_str, &hints, &addrs) != 0) {
+        return -1;
+    }
+
+    // TODO: try all the addresses if there's more than one?
+    int family = addrs[0].ai_family;
+    int protocol = addrs[0].ai_protocol;
+    socklen_t addr_len = addrs[0].ai_addrlen;
+    struct sockaddr_storage addr;
+    memcpy(&addr, addrs[0].ai_addr, addr_len);
+
+    freeaddrinfo(addrs);
+
+    // The Mac doesn't have SOCK_NONBLOCK.
+    int s = socket(family, type, protocol);
+    if (s == -1 || toggle_O_NONBLOCK(s) == -1) return -1;
+
+    int rc = connect(s, (const struct sockaddr*) &addr, addr_len);
+    if (rc == 0) {
+        return toggle_O_NONBLOCK(s);
+    } else if (rc == -1 && errno != EINPROGRESS) {
+        close(s);
+        return -1;
+    }
+
+    fd_set r_set;
+    FD_ZERO(&r_set);
+    FD_SET(s, &r_set);
+    fd_set w_set = r_set;
+
+    struct timeval ts;
     ts.tv_sec = timeout;
     ts.tv_usec = 0;
-
-    hp = gethostbyname(host);
-    if (hp == 0) return -1;
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = hp->h_addrtype;
-    addr.sin_port = htons(port);
-    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
-
-    s = socket(hp->h_addrtype, type, 0);
-    if (s < 0) return -1;
-
-    if ((flags = fcntl(s, F_GETFL, 0)) < 0) {
+    if ((rc = select(s + 1, &r_set, &w_set, NULL, (timeout != 0) ? &ts : NULL)) == -1) {
         close(s);
         return -1;
     }
-
-    if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
-        close(s);
-        return -1;
-    }
-
-    if ((ret = connect(s, (struct sockaddr *) &addr, sizeof(addr))) < 0) {
-        if (errno != EINPROGRESS) {
-            close(s);
-            return -1;
-        }
-    }
-
-    if (ret == 0)
-        goto done;
-
-    FD_ZERO(&rset);
-    FD_SET(s, &rset);
-    wset = rset;
-
-    if ((ret = select(s + 1, &rset, &wset, NULL, (timeout) ? &ts : NULL)) < 0) {
-        close(s);
-        return -1;
-    }
-    if (ret == 0) {   // we had a timeout
+    if (rc == 0) {   // we had a timeout
         errno = ETIMEDOUT;
         close(s);
         return -1;
     }
 
-    if (FD_ISSET(s, &rset) || FD_ISSET(s, &wset)) {
+    int error = 0;
+    socklen_t len = sizeof(error);
+    if (FD_ISSET(s, &r_set) || FD_ISSET(s, &w_set)) {
         if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
             close(s);
             return -1;
@@ -115,11 +112,9 @@
         return -1;
     }
 
-done:
-    if (fcntl(s, F_SETFL, flags) < 0) {
-        close(s);
-        return -1;
-    }
+    return toggle_O_NONBLOCK(s);
+}
 
-    return s;
+int socket_network_client(const char* host, int port, int type) {
+    return socket_network_client_timeout(host, port, type, 0);
 }
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index f63497b..a9671a9 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -109,6 +109,13 @@
   }
 }
 
+static void ReleaseAppCodeCacheDir() {
+  if (app_code_cache_dir != nullptr) {
+    delete[] app_code_cache_dir;
+    app_code_cache_dir = nullptr;
+  }
+}
+
 // We only allow simple names for the library. It is supposed to be a file in
 // /system/lib or /vendor/lib. Only allow a small range of characters, that is
 // names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z].
@@ -162,8 +169,7 @@
 static void CloseNativeBridge(bool with_error) {
   state = NativeBridgeState::kClosed;
   had_error |= with_error;
-  delete[] app_code_cache_dir;
-  app_code_cache_dir = nullptr;
+  ReleaseAppCodeCacheDir();
 }
 
 bool LoadNativeBridge(const char* nb_library_filename,
@@ -406,16 +412,16 @@
     if (stat(app_code_cache_dir, &st) == -1) {
       if (errno == ENOENT) {
         if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) {
-          ALOGE("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
-          CloseNativeBridge(true);
+          ALOGW("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
+          ReleaseAppCodeCacheDir();
         }
       } else {
-        ALOGE("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
-        CloseNativeBridge(true);
+        ALOGW("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
+        ReleaseAppCodeCacheDir();
       }
     } else if (!S_ISDIR(st.st_mode)) {
-      ALOGE("Code cache is not a directory %s.", app_code_cache_dir);
-      CloseNativeBridge(true);
+      ALOGW("Code cache is not a directory %s.", app_code_cache_dir);
+      ReleaseAppCodeCacheDir();
     }
 
     // If we're still PreInitialized (dind't fail the code cache checks) try to initialize.
@@ -424,8 +430,7 @@
         SetupEnvironment(callbacks, env, instruction_set);
         state = NativeBridgeState::kInitialized;
         // We no longer need the code cache path, release the memory.
-        delete[] app_code_cache_dir;
-        app_code_cache_dir = nullptr;
+        ReleaseAppCodeCacheDir();
       } else {
         // Unload the library.
         dlclose(native_bridge_handle);
diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk
index 285e8c2..7265939 100644
--- a/libnativebridge/tests/Android.mk
+++ b/libnativebridge/tests/Android.mk
@@ -9,6 +9,7 @@
 test_src_files := \
     CodeCacheCreate_test.cpp \
     CodeCacheExists_test.cpp \
+    CodeCacheStatFail_test.cpp \
     CompleteFlow_test.cpp \
     InvalidCharsNativeBridge_test.cpp \
     NativeBridge2Signal_test.cpp \
diff --git a/libnativebridge/tests/CodeCacheStatFail_test.cpp b/libnativebridge/tests/CodeCacheStatFail_test.cpp
new file mode 100644
index 0000000..4ea519e
--- /dev/null
+++ b/libnativebridge/tests/CodeCacheStatFail_test.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 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 "NativeBridgeTest.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+namespace android {
+
+// Tests that the bridge is initialized without errors if the code_cache is
+// existed as a file.
+TEST_F(NativeBridgeTest, CodeCacheStatFail) {
+    int fd = creat(kCodeCache, O_RDWR);
+    ASSERT_NE(-1, fd);
+    close(fd);
+
+    struct stat st;
+    ASSERT_EQ(-1, stat(kCodeCacheStatFail, &st));
+    ASSERT_EQ(ENOTDIR, errno);
+
+    // Init
+    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
+    ASSERT_TRUE(PreInitializeNativeBridge(kCodeCacheStatFail, "isa"));
+    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
+    ASSERT_TRUE(NativeBridgeAvailable());
+    ASSERT_FALSE(NativeBridgeError());
+
+    // Clean up
+    UnloadNativeBridge();
+
+    ASSERT_FALSE(NativeBridgeError());
+    unlink(kCodeCache);
+}
+
+}  // namespace android
diff --git a/libnativebridge/tests/NativeBridgeTest.h b/libnativebridge/tests/NativeBridgeTest.h
index 6a5c126..d489420 100644
--- a/libnativebridge/tests/NativeBridgeTest.h
+++ b/libnativebridge/tests/NativeBridgeTest.h
@@ -24,6 +24,7 @@
 
 constexpr const char* kNativeBridgeLibrary = "libnativebridge-dummy.so";
 constexpr const char* kCodeCache = "./code_cache";
+constexpr const char* kCodeCacheStatFail = "./code_cache/temp";
 
 namespace android {
 
diff --git a/libsparse/sparse_crc32.h b/libsparse/sparse_crc32.h
index cad8a86..50cd9e9 100644
--- a/libsparse/sparse_crc32.h
+++ b/libsparse/sparse_crc32.h
@@ -14,7 +14,19 @@
  * limitations under the License.
  */
 
+#ifndef _LIBSPARSE_SPARSE_CRC32_H_
+#define _LIBSPARSE_SPARSE_CRC32_H_
+
 #include <stdint.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 uint32_t sparse_crc32(uint32_t crc, const void *buf, size_t size);
 
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 05d8fe0..d6dad2d 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -26,7 +26,7 @@
 #
 # create some directories (some are mount points)
 LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
-    sbin dev proc sys system data oem)
+    sbin dev proc sys system data oem acct cache config storage mnt root)
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 72df0f5..b7a593f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -17,11 +17,11 @@
     # Set the security context of /adb_keys if present.
     restorecon /adb_keys
 
-    start ueventd
-
-    # create mountpoints
+    # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.
     mkdir /mnt 0775 root system
 
+    start ueventd
+
 on init
     sysclktz 0
 
@@ -32,8 +32,7 @@
     # Link /vendor to /system/vendor for devices without a vendor partition.
     symlink /system/vendor /vendor
 
-    # Create cgroup mount point for cpu accounting
-    mkdir /acct
+    # Mount cgroup mount point for cpu accounting
     mount cgroup none /acct cpuacct
     mkdir /acct/uid
 
@@ -50,11 +49,6 @@
     chown root system /sys/fs/cgroup/memory/sw/tasks
     chmod 0660 /sys/fs/cgroup/memory/sw/tasks
 
-    mkdir /system
-    mkdir /data 0771 system system
-    mkdir /cache 0770 system cache
-    mkdir /config 0500 root root
-
     # See storage config details at http://source.android.com/tech/storage/
     mkdir /mnt/shell 0700 shell shell
     mkdir /mnt/media_rw 0700 media_rw media_rw