Merge "Add 24-bit packed to audio_format_t"
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 422a86a..e0a2d96 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -1,7 +1,5 @@
 # Copyright 2005 The Android Open Source Project
 
-ifneq ($(filter arm mips x86,$(TARGET_ARCH)),)
-
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -19,8 +17,13 @@
 	-Wall \
 	-Wno-array-bounds \
 	-Werror \
+	-Wno-unused-parameter \
 
-LOCAL_MODULE := debuggerd
+ifeq ($(TARGET_IS_64_BIT),true)
+    LOCAL_MODULE := debuggerd64
+else
+    LOCAL_MODULE := debuggerd
+endif
 
 ifeq ($(ARCH_ARM_HAVE_VFP),true)
 LOCAL_CFLAGS += -DWITH_VFP
@@ -59,12 +62,10 @@
 LOCAL_CFLAGS += -DWITH_VFP_D32
 endif # ARCH_ARM_HAVE_VFP_D32
 
-LOCAL_SRC_FILES := vfp-crasher.c vfp.S
+LOCAL_SRC_FILES := vfp-crasher.c $(TARGET_ARCH)/vfp.S
 LOCAL_MODULE := vfp-crasher
 LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
 LOCAL_MODULE_TAGS := optional
 LOCAL_SHARED_LIBRARIES := libcutils liblog libc
 include $(BUILD_EXECUTABLE)
 endif # ARCH_ARM_HAVE_VFP == true
-
-endif # arm or x86 in TARGET_ARCH
diff --git a/debuggerd/arm/machine.cpp b/debuggerd/arm/machine.cpp
index 3fba6db..fd2f69b 100644
--- a/debuggerd/arm/machine.cpp
+++ b/debuggerd/arm/machine.cpp
@@ -38,65 +38,6 @@
 #endif
 #endif
 
-static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) {
-  char code_buffer[64];       // actual 8+1+((8+1)*4) + 1 == 45
-  char ascii_buffer[32];      // actual 16 + 1 == 17
-  uintptr_t p, end;
-
-  p = addr & ~3;
-  p -= 32;
-  if (p > addr) {
-    // catch underflow
-    p = 0;
-  }
-  // Dump more memory content for the crashing thread.
-  end = p + 256;
-  // catch overflow; 'end - p' has to be multiples of 16
-  while (end < p)
-    end -= 16;
-
-  // Dump the code around PC as:
-  //  addr     contents                             ascii
-  //  00008d34 ef000000 e8bd0090 e1b00000 512fff1e  ............../Q
-  //  00008d44 ea00b1f9 e92d0090 e3a070fc ef000000  ......-..p......
-  while (p < end) {
-    char* asc_out = ascii_buffer;
-
-    sprintf(code_buffer, "%08x ", p);
-
-    int i;
-    for (i = 0; i < 4; i++) {
-      // If we see (data == -1 && errno != 0), we know that the ptrace
-      // call failed, probably because we're dumping memory in an
-      // unmapped or inaccessible page.  I don't know if there's
-      // value in making that explicit in the output -- it likely
-      // just complicates parsing and clarifies nothing for the
-      // enlightened reader.
-      long data = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(p), NULL);
-      sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);
-
-      // Enable the following code blob to dump ASCII values
-#if 0
-      int j;
-      for (j = 0; j < 4; j++) {
-        // Our isprint() allows high-ASCII characters that display
-        // differently (often badly) in different viewers, so we
-        // just use a simpler test.
-        char val = (data >> (j*8)) & 0xff;
-        if (val >= 0x20 && val < 0x7f) {
-          *asc_out++ = val;
-        } else {
-          *asc_out++ = '.';
-        }
-      }
-#endif
-      p += 4;
-    }
-    *asc_out = '\0';
-    _LOG(log, scope_flags, "    %s %s\n", code_buffer, ascii_buffer);
-  }
-}
-
 // If configured to do so, dump memory around *all* registers
 // for the crashing thread.
 void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) {
diff --git a/debuggerd/vfp.S b/debuggerd/arm/vfp.S
similarity index 100%
rename from debuggerd/vfp.S
rename to debuggerd/arm/vfp.S
diff --git a/debuggerd/arm64/crashglue.S b/debuggerd/arm64/crashglue.S
new file mode 100644
index 0000000..b06b67c
--- /dev/null
+++ b/debuggerd/arm64/crashglue.S
@@ -0,0 +1,47 @@
+.globl crash1
+.type crash1, %function
+.globl crashnostack
+.type crashnostack, %function
+
+crash1:
+	ldr x0, =0xa5a50000
+	ldr x1, =0xa5a50001
+	ldr x2, =0xa5a50002
+	ldr x3, =0xa5a50003
+	ldr x4, =0xa5a50004
+	ldr x5, =0xa5a50005
+	ldr x6, =0xa5a50006
+	ldr x7, =0xa5a50007
+	ldr x8, =0xa5a50008
+	ldr x9, =0xa5a50009
+	ldr x10, =0xa5a50010
+	ldr x11, =0xa5a50011
+	ldr x12, =0xa5a50012
+	ldr x13, =0xa5a50013
+	ldr x14, =0xa5a50014
+	ldr x15, =0xa5a50015
+	ldr x16, =0xa5a50016
+	ldr x17, =0xa5a50017
+	ldr x18, =0xa5a50018
+	ldr x19, =0xa5a50019
+	ldr x20, =0xa5a50020
+	ldr x21, =0xa5a50021
+	ldr x22, =0xa5a50022
+	ldr x23, =0xa5a50023
+	ldr x24, =0xa5a50024
+	ldr x25, =0xa5a50025
+	ldr x26, =0xa5a50026
+	ldr x27, =0xa5a50027
+	ldr x28, =0xa5a50028
+	ldr x29, =0xa5a50029
+
+	mov x30, xzr
+	ldr x30, [x30]
+	b .
+
+
+crashnostack:
+	mov x0, xzr
+	add sp, x0, xzr
+	ldr x0, [x0]
+	b .
diff --git a/debuggerd/arm64/machine.cpp b/debuggerd/arm64/machine.cpp
new file mode 100644
index 0000000..7159228
--- /dev/null
+++ b/debuggerd/arm64/machine.cpp
@@ -0,0 +1,123 @@
+/*
+ *
+ * Copyright 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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+#include <sys/uio.h>
+#include <linux/elf.h>
+
+#include "../utility.h"
+#include "../machine.h"
+
+/* enable to dump memory pointed to by every register */
+#define DUMP_MEMORY_FOR_ALL_REGISTERS 1
+
+/*
+ * If configured to do so, dump memory around *all* registers
+ * for the crashing thread.
+ */
+void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) {
+    struct user_pt_regs regs;
+    struct iovec io;
+    io.iov_base = &regs;
+    io.iov_len = sizeof(regs);
+
+    if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, &io) == -1) {
+        _LOG(log, scope_flags, "%s: ptrace failed to get registers: %s\n",
+             __func__, strerror(errno));
+        return;
+    }
+
+    if (IS_AT_FAULT(scope_flags) && DUMP_MEMORY_FOR_ALL_REGISTERS) {
+        for (int reg = 0; reg < 31; reg++) {
+            uintptr_t addr = regs.regs[reg];
+
+            /*
+             * Don't bother if it looks like a small int or ~= null, or if
+             * it's in the kernel area.
+             */
+            if (addr < 4096 || addr >= (1UL<<63)) {
+                continue;
+            }
+
+            _LOG(log, scope_flags | SCOPE_SENSITIVE, "\nmemory near x%d:\n", reg);
+            dump_memory(log, tid, addr, scope_flags | SCOPE_SENSITIVE);
+        }
+    }
+
+    _LOG(log, scope_flags, "\ncode around pc:\n");
+    dump_memory(log, tid, (uintptr_t)regs.pc, scope_flags);
+
+    if (regs.pc != regs.sp) {
+        _LOG(log, scope_flags, "\ncode around sp:\n");
+        dump_memory(log, tid, (uintptr_t)regs.sp, scope_flags);
+    }
+}
+
+void dump_registers(log_t* log, pid_t tid, int scope_flags)
+{
+  struct user_pt_regs r;
+  struct iovec io;
+  io.iov_base = &r;
+  io.iov_len = sizeof(r);
+
+  bool only_in_tombstone = !IS_AT_FAULT(scope_flags);
+
+  if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRSTATUS, (void*) &io) == -1) {
+    _LOG(log, scope_flags, "ptrace error: %s\n", strerror(errno));
+    return;
+  }
+
+  for (int i = 0; i < 28; i += 4) {
+    _LOG(log, scope_flags, "    x%-2d  %016lx  x%-2d  %016lx  x%-2d  %016lx  x%-2d  %016lx\n",
+         i, (uint64_t)r.regs[i],
+         i+1, (uint64_t)r.regs[i+1],
+         i+2, (uint64_t)r.regs[i+2],
+         i+3, (uint64_t)r.regs[i+3]);
+  }
+
+  _LOG(log, scope_flags, "    x28  %016lx  x29  %016lx  x30  %016lx\n",
+       (uint64_t)r.regs[28], (uint64_t)r.regs[29], (uint64_t)r.regs[30]);
+
+  _LOG(log, scope_flags, "    sp   %016lx  pc   %016lx\n",
+       (uint64_t)r.sp, (uint64_t)r.pc);
+
+
+  struct user_fpsimd_state f;
+  io.iov_base = &f;
+  io.iov_len = sizeof(f);
+
+  if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRFPREG, (void*) &io) == -1) {
+    _LOG(log, scope_flags, "ptrace error: %s\n", strerror(errno));
+    return;
+  }
+
+  for (int i = 0; i < 32; i += 4) {
+    _LOG(log, scope_flags, "    v%-2d  %016lx  v%-2d  %016lx  v%-2d  %016lx  v%-2d  %016lx\n",
+         i, (uint64_t)f.vregs[i],
+         i+1, (uint64_t)f.vregs[i+1],
+         i+2, (uint64_t)f.vregs[i+2],
+         i+3, (uint64_t)f.vregs[i+3]);
+  }
+}
diff --git a/debuggerd/arm64/vfp.S b/debuggerd/arm64/vfp.S
new file mode 100644
index 0000000..bf12c22
--- /dev/null
+++ b/debuggerd/arm64/vfp.S
@@ -0,0 +1,42 @@
+    .text
+    .align 2
+    .global crash
+    .type crash, %function
+crash:
+    fmov   d0, XZR
+    fmov   d1, 1.0
+    fmov   d2, 2.0
+    fmov   d3, 3.0
+    fmov   d4, 4.0
+    fmov   d5, 5.0
+    fmov   d6, 6.0
+    fmov   d7, 7.0
+    fmov   d8, 8.0
+    fmov   d9, 9.0
+    fmov   d10, 10.0
+    fmov   d11, 11.0
+    fmov   d12, 12.0
+    fmov   d13, 13.0
+    fmov   d14, 14.0
+    fmov   d15, 15.0
+    fmov   d16, 16.0
+    fmov   d17, 17.0
+    fmov   d18, 18.0
+    fmov   d19, 19.0
+    fmov   d20, 20.0
+    fmov   d21, 21.0
+    fmov   d22, 22.0
+    fmov   d23, 23.0
+    fmov   d24, 24.0
+    fmov   d25, 25.0
+    fmov   d26, 26.0
+    fmov   d27, 27.0
+    fmov   d28, 28.0
+    fmov   d29, 29.0
+    fmov   d30, 30.0
+    fmov   d31, 31.0
+
+    mov       x0, xzr
+    str       x0, [x0]
+    br        x30
+
diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c
index 5ecb1a5..0033948 100644
--- a/debuggerd/crasher.c
+++ b/debuggerd/crasher.c
@@ -23,19 +23,6 @@
 void crashnostack(void);
 static int do_action(const char* arg);
 
-static void debuggerd_connect()
-{
-    char tmp[1];
-    int s;
-    sprintf(tmp, "%d", gettid());
-    s = socket_local_client("android:debuggerd",
-            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-    if(s >= 0) {
-        read(s, tmp, 1);
-        close(s);
-    }
-}
-
 static void maybeabort() {
     if(time(0) != 42) {
         abort();
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index de8ba9d..c39aaf6 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -205,7 +205,8 @@
     return -1;
   }
   if (status == sizeof(debugger_msg_t)) {
-    XLOG("crash request of size %d abort_msg_address=%#08x\n", status, msg.abort_msg_address);
+    XLOG("crash request of size %d abort_msg_address=0x%" PRIPTR "\n",
+         status, msg.abort_msg_address);
   } else {
     LOG("invalid crash request of size %d (from pid=%d uid=%d)\n", status, cr.pid, cr.uid);
     return -1;
diff --git a/debuggerd/mips/machine.cpp b/debuggerd/mips/machine.cpp
index d1a7f2d..7b4e29e 100644
--- a/debuggerd/mips/machine.cpp
+++ b/debuggerd/mips/machine.cpp
@@ -34,61 +34,6 @@
 
 #define R(x) (static_cast<unsigned int>(x))
 
-static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) {
-  char code_buffer[64];       // actual 8+1+((8+1)*4) + 1 == 45
-  char ascii_buffer[32];      // actual 16 + 1 == 17
-  uintptr_t p, end;
-
-  p = addr & ~3;
-  p -= 32;
-  if (p > addr) {
-    // catch underflow
-    p = 0;
-  }
-  end = p + 80;
-  // catch overflow; 'end - p' has to be multiples of 16
-  while (end < p)
-    end -= 16;
-
-  // Dump the code around PC as:
-  //  addr     contents                             ascii
-  //  00008d34 ef000000 e8bd0090 e1b00000 512fff1e  ............../Q
-  //  00008d44 ea00b1f9 e92d0090 e3a070fc ef000000  ......-..p......
-  while (p < end) {
-    char* asc_out = ascii_buffer;
-
-    sprintf(code_buffer, "%08x ", p);
-
-    int i;
-    for (i = 0; i < 4; i++) {
-      // If we see (data == -1 && errno != 0), we know that the ptrace
-      // call failed, probably because we're dumping memory in an
-      // unmapped or inaccessible page.  I don't know if there's
-      // value in making that explicit in the output -- it likely
-      // just complicates parsing and clarifies nothing for the
-      // enlightened reader.
-      long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL);
-      sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);
-
-      int j;
-      for (j = 0; j < 4; j++) {
-        // Our isprint() allows high-ASCII characters that display
-        // differently (often badly) in different viewers, so we
-        // just use a simpler test.
-        char val = (data >> (j*8)) & 0xff;
-        if (val >= 0x20 && val < 0x7f) {
-          *asc_out++ = val;
-        } else {
-          *asc_out++ = '.';
-        }
-      }
-      p += 4;
-    }
-    *asc_out = '\0';
-    _LOG(log, scope_flags, "    %s %s\n", code_buffer, ascii_buffer);
-  }
-}
-
 // If configured to do so, dump memory around *all* registers
 // for the crashing thread.
 void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) {
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
old mode 100644
new mode 100755
index f8ec8cf..5e3d729
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-#include <stddef.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
 #include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <time.h>
 #include <sys/ptrace.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
-#include <inttypes.h>
+#include <sys/un.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -36,9 +38,6 @@
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 
-#include <sys/socket.h>
-#include <linux/un.h>
-
 #include <selinux/android.h>
 
 #include <UniquePtr.h>
@@ -51,6 +50,7 @@
 
 #define MAX_TOMBSTONES  10
 #define TOMBSTONE_DIR   "/data/tombstones"
+#define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d")
 
 // Must match the path defined in NativeCrashListener.java
 #define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
@@ -60,7 +60,6 @@
   typeof(y) __dummy2;     \
   (void)(&__dummy1 == &__dummy2); }
 
-
 static bool signal_has_address(int sig) {
   switch (sig) {
     case SIGILL:
@@ -180,9 +179,9 @@
   if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
     _LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
   } else if (signal_has_address(sig)) {
-    _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %0*" PRIxPTR "\n",
+    _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %" PRIPTR "\n",
          sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code),
-         sizeof(uintptr_t)*2, reinterpret_cast<uintptr_t>(si.si_addr));
+         reinterpret_cast<uintptr_t>(si.si_addr));
   } else {
     _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n",
          sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
@@ -227,7 +226,7 @@
 static void dump_stack_segment(
     Backtrace* backtrace, log_t* log, int scope_flags, uintptr_t* sp, size_t words, int label) {
   for (size_t i = 0; i < words; i++) {
-    uint32_t stack_content;
+    word_t stack_content;
     if (!backtrace->ReadWord(*sp, &stack_content)) {
       break;
     }
@@ -244,32 +243,32 @@
     if (!func_name.empty()) {
       if (!i && label >= 0) {
         if (offset) {
-          _LOG(log, scope_flags, "    #%02d  %08x  %08x  %s (%s+%u)\n",
+          _LOG(log, scope_flags, "    #%02d  %" PRIPTR "  %" PRIPTR "  %s (%s+%" PRIuPTR ")\n",
                label, *sp, stack_content, map_name, func_name.c_str(), offset);
         } else {
-          _LOG(log, scope_flags, "    #%02d  %08x  %08x  %s (%s)\n",
+          _LOG(log, scope_flags, "    #%02d  %" PRIPTR "  %" PRIPTR "  %s (%s)\n",
                label, *sp, stack_content, map_name, func_name.c_str());
         }
       } else {
         if (offset) {
-          _LOG(log, scope_flags, "         %08x  %08x  %s (%s+%u)\n",
+          _LOG(log, scope_flags, "         %" PRIPTR "  %" PRIPTR "  %s (%s+%" PRIuPTR ")\n",
                *sp, stack_content, map_name, func_name.c_str(), offset);
         } else {
-          _LOG(log, scope_flags, "         %08x  %08x  %s (%s)\n",
+          _LOG(log, scope_flags, "         %" PRIPTR "  %" PRIPTR "  %s (%s)\n",
                *sp, stack_content, map_name, func_name.c_str());
         }
       }
     } else {
       if (!i && label >= 0) {
-        _LOG(log, scope_flags, "    #%02d  %08x  %08x  %s\n",
+        _LOG(log, scope_flags, "    #%02d  %" PRIPTR "  %" PRIPTR "  %s\n",
              label, *sp, stack_content, map_name);
       } else {
-        _LOG(log, scope_flags, "         %08x  %08x  %s\n",
+        _LOG(log, scope_flags, "         %" PRIPTR "  %" PRIPTR "  %s\n",
              *sp, stack_content, map_name);
       }
     }
 
-    *sp += sizeof(uint32_t);
+    *sp += sizeof(word_t);
   }
 }
 
@@ -292,7 +291,7 @@
   scope_flags |= SCOPE_SENSITIVE;
 
   // Dump a few words before the first frame.
-  uintptr_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(uint32_t);
+  word_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(word_t);
   dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, -1);
 
   // Dump a few words from all successive frames.
@@ -312,7 +311,7 @@
         _LOG(log, scope_flags, "         ........  ........\n");
       }
     } else {
-      size_t words = frame->stack_size / sizeof(uint32_t);
+      size_t words = frame->stack_size / sizeof(word_t);
       if (words == 0) {
         words = 1;
       } else if (words > STACK_WORDS) {
@@ -335,7 +334,7 @@
 
 static void dump_map(log_t* log, const backtrace_map_t* map, const char* what, int scope_flags) {
   if (map != NULL) {
-    _LOG(log, scope_flags, "    %08x-%08x %c%c%c %s\n", map->start, map->end,
+    _LOG(log, scope_flags, "    %" PRIPTR "-%" PRIPTR " %c%c%c %s\n", map->start, map->end,
          (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-',
          (map->flags & PROT_EXEC) ? 'x' : '-', map->name.c_str());
   } else {
@@ -361,7 +360,7 @@
     return;
   }
 
-  _LOG(log, scope_flags, "\nmemory map around fault addr %" PRIxPTR ":\n",
+  _LOG(log, scope_flags, "\nmemory map around fault addr %" PRIPTR ":\n",
        reinterpret_cast<uintptr_t>(si.si_addr));
 
   // Search for a match, or for a hole where the match would be.  The list
@@ -568,24 +567,15 @@
   memset(msg, 0, sizeof(msg));
   char* p = &msg[0];
   while (p < &msg[sizeof(msg)]) {
-    uint32_t data;
+    word_t data;
+    size_t len = sizeof(word_t);
     if (!backtrace->ReadWord(address, &data)) {
       break;
     }
-    address += sizeof(uint32_t);
+    address += sizeof(word_t);
 
-    if ((*p++ = (data >>  0) & 0xff) == 0) {
-      break;
-    }
-    if ((*p++ = (data >>  8) & 0xff) == 0) {
-      break;
-    }
-    if ((*p++ = (data >> 16) & 0xff) == 0) {
-      break;
-    }
-    if ((*p++ = (data >> 24) & 0xff) == 0) {
-      break;
-    }
+    while (len > 0 && (*p++ = (data >> (sizeof(word_t) - len) * 8) & 0xff) != 0)
+       len--;
   }
   msg[sizeof(msg) - 1] = '\0';
 
@@ -657,7 +647,11 @@
 //
 // Returns the path of the tombstone file, allocated using malloc().  Caller must free() it.
 static char* find_and_open_tombstone(int* fd) {
+#ifdef __aarch64__
+  long mtime = LONG_MAX;
+#else
   unsigned long mtime = ULONG_MAX;
+#endif
   struct stat sb;
 
   // XXX: Our stat.st_mtime isn't time_t. If it changes, as it probably ought
@@ -669,7 +663,7 @@
   char path[128];
   int oldest = 0;
   for (int i = 0; i < MAX_TOMBSTONES; i++) {
-    snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", i);
+    snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, i);
 
     if (!stat(path, &sb)) {
       if (sb.st_mtime < mtime) {
@@ -690,7 +684,7 @@
   }
 
   // we didn't find an available file, so we clobber the oldest one
-  snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", oldest);
+  snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, oldest);
   *fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
   if (*fd < 0) {
     LOG("failed to open tombstone file '%s': %s\n", path, strerror(errno));
@@ -733,8 +727,13 @@
 char* engrave_tombstone(
     pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address, bool dump_sibling_threads,
     bool quiet, bool* detach_failed, int* total_sleep_time_usec) {
-  mkdir(TOMBSTONE_DIR, 0755);
-  chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM);
+  if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) {
+      LOG("failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno));
+  }
+
+  if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) {
+      LOG("failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno));
+  }
 
   if (selinux_android_restorecon(TOMBSTONE_DIR) == -1) {
     *detach_failed = false;
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index 35f061e..9b20914 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -14,19 +14,17 @@
  * limitations under the License.
  */
 
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
+#include "utility.h"
+
 #include <errno.h>
-#include <unistd.h>
 #include <signal.h>
-#include <log/logd.h>
+#include <string.h>
+#include <unistd.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
-#include <arpa/inet.h>
-#include <assert.h>
 
-#include "utility.h"
+#include <backtrace/Backtrace.h>
+#include <log/logd.h>
 
 const int sleep_time_usec = 50000;         // 0.05 seconds
 const int max_total_sleep_usec = 10000000; // 10 seconds
@@ -34,7 +32,7 @@
 static int write_to_am(int fd, const char* buf, int len) {
   int to_write = len;
   while (to_write > 0) {
-    int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) );
+    int written = TEMP_FAILURE_RETRY(write(fd, buf + len - to_write, to_write));
     if (written < 0) {
       // hard failure
       LOG("AM write failure (%d / %s)\n", errno, strerror(errno));
@@ -46,34 +44,28 @@
 }
 
 void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) {
-  char buf[512];
-  bool want_tfd_write;
-  bool want_log_write;
-  bool want_amfd_write;
-  int len = 0;
+  bool want_tfd_write = log && log->tfd >= 0;
+  bool want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
+  bool want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
 
+  char buf[512];
   va_list ap;
   va_start(ap, fmt);
+  vsnprintf(buf, sizeof(buf), fmt, ap);
+  va_end(ap);
 
-  // where is the information going to go?
-  want_tfd_write = log && log->tfd >= 0;
-  want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
-  want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
-
-  // if we're going to need the literal string, generate it once here
-  if (want_tfd_write || want_amfd_write) {
-    vsnprintf(buf, sizeof(buf), fmt, ap);
-    len = strlen(buf);
+  size_t len = strlen(buf);
+  if (len <= 0) {
+    return;
   }
 
   if (want_tfd_write) {
-    write(log->tfd, buf, len);
+    TEMP_FAILURE_RETRY(write(log->tfd, buf, len));
   }
 
   if (want_log_write) {
-    // whatever goes to logcat also goes to the Activity Manager
-    __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
-    if (want_amfd_write && len > 0) {
+    __android_log_write(ANDROID_LOG_INFO, "DEBUG", buf);
+    if (want_amfd_write) {
       int written = write_to_am(log->amfd, buf, len);
       if (written <= 0) {
         // timeout or other failure on write; stop informing the activity manager
@@ -81,7 +73,6 @@
       }
     }
   }
-  va_end(ap);
 }
 
 int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
@@ -127,3 +118,77 @@
     *total_sleep_time_usec += sleep_time_usec;
   }
 }
+
+#if defined (__mips__)
+#define DUMP_MEMORY_AS_ASCII 1
+#else
+#define DUMP_MEMORY_AS_ASCII 0
+#endif
+
+void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) {
+    char code_buffer[64];
+    char ascii_buffer[32];
+    uintptr_t p, end;
+
+    p = addr & ~(sizeof(long) - 1);
+    /* Dump 32 bytes before addr */
+    p -= 32;
+    if (p > addr) {
+        /* catch underflow */
+        p = 0;
+    }
+    /* Dump 256 bytes */
+    end = p + 256;
+    /* catch overflow; 'end - p' has to be multiples of 16 */
+    while (end < p) {
+        end -= 16;
+    }
+
+    /* Dump the code around PC as:
+     *  addr             contents                           ascii
+     *  0000000000008d34 ef000000e8bd0090 e1b00000512fff1e  ............../Q
+     *  0000000000008d44 ea00b1f9e92d0090 e3a070fcef000000  ......-..p......
+     * On 32-bit machines, there are still 16 bytes per line but addresses and
+     * words are of course presented differently.
+     */
+    while (p < end) {
+        char* asc_out = ascii_buffer;
+
+        int len = snprintf(code_buffer, sizeof(code_buffer), "%" PRIPTR " ", p);
+
+        for (size_t i = 0; i < 16/sizeof(long); i++) {
+            long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL);
+            if (data == -1 && errno != 0) {
+                // ptrace failed, probably because we're dumping memory in an
+                // unmapped or inaccessible page.
+#ifdef __LP64__
+                len += sprintf(code_buffer + len, "---------------- ");
+#else
+                len += sprintf(code_buffer + len, "-------- ");
+#endif
+            } else {
+                len += sprintf(code_buffer + len, "%" PRIPTR " ",
+                               static_cast<uintptr_t>(data));
+            }
+
+#if DUMP_MEMORY_AS_ASCII
+            for (size_t j = 0; j < sizeof(long); j++) {
+                /*
+                 * Our isprint() allows high-ASCII characters that display
+                 * differently (often badly) in different viewers, so we
+                 * just use a simpler test.
+                 */
+                char val = (data >> (j*8)) & 0xff;
+                if (val >= 0x20 && val < 0x7f) {
+                    *asc_out++ = val;
+                } else {
+                    *asc_out++ = '.';
+                }
+            }
+#endif
+            p += sizeof(long);
+        }
+        *asc_out = '\0';
+        _LOG(log, scope_flags, "    %s %s\n", code_buffer, ascii_buffer);
+    }
+}
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 1f006ed..0f88605 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -18,8 +18,8 @@
 #ifndef _DEBUGGERD_UTILITY_H
 #define _DEBUGGERD_UTILITY_H
 
-#include <stddef.h>
 #include <stdbool.h>
+#include <sys/types.h>
 
 typedef struct {
     /* tombstone file descriptor */
@@ -63,4 +63,6 @@
 int wait_for_signal(pid_t tid, int* total_sleep_time_usec);
 void wait_for_stop(pid_t tid, int* total_sleep_time_usec);
 
+void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags);
+
 #endif // _DEBUGGERD_UTILITY_H
diff --git a/debuggerd/x86_64/crashglue.S b/debuggerd/x86_64/crashglue.S
new file mode 100644
index 0000000..4d2a5c0
--- /dev/null
+++ b/debuggerd/x86_64/crashglue.S
@@ -0,0 +1,15 @@
+.globl crash1
+.globl crashnostack
+
+crash1:
+	movl $0xa5a50000, %eax
+	movl $0xa5a50001, %ebx
+	movl $0xa5a50002, %ecx
+
+	movl $0, %edx
+	jmp *%rdx
+
+
+crashnostack:
+	movl $0, %ebp
+	jmp *%rbp
diff --git a/debuggerd/x86_64/machine.cpp b/debuggerd/x86_64/machine.cpp
new file mode 100755
index 0000000..406851a
--- /dev/null
+++ b/debuggerd/x86_64/machine.cpp
@@ -0,0 +1,51 @@
+/*
+** Copyright 2013, 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 <stddef.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+
+#include "../utility.h"
+#include "../machine.h"
+
+void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) {
+}
+
+void dump_registers(log_t* log, pid_t tid, int scope_flags) {
+    struct user_regs_struct r;
+    if (ptrace(PTRACE_GETREGS, tid, 0, &r) == -1) {
+        _LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno));
+        return;
+    }
+    _LOG(log, scope_flags, "    rax %016lx  rbx %016lx  rcx %016lx  rdx %016lx\n",
+         r.rax, r.rbx, r.rcx, r.rdx);
+    _LOG(log, scope_flags, "    rsi %016lx  rdi %016lx\n",
+         r.rsi, r.rdi);
+    _LOG(log, scope_flags, "    r8  %016lx  r9  %016lx  r10 %016lx  r11 %016lx\n",
+         r.r8, r.r9, r.r10, r.r11);
+    _LOG(log, scope_flags, "    r12 %016lx  r13 %016lx  r14 %016lx  r15 %016lx\n",
+         r.r12, r.r13, r.r14, r.r15);
+    _LOG(log, scope_flags, "    cs  %016lx  ss  %016lx\n",
+         r.cs, r.ss);
+    _LOG(log, scope_flags, "    rip %016lx  rbp %016lx  rsp %016lx  eflags %016lx\n",
+         r.rip, r.rbp, r.rsp, r.eflags);
+}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 790598a..165ebd4 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -3,7 +3,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c
+LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c fs_mgr_fstab.c
 
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 24ce806..4c2f247 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -54,55 +54,6 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
-struct flag_list {
-    const char *name;
-    unsigned flag;
-};
-
-static struct flag_list mount_flags[] = {
-    { "noatime",    MS_NOATIME },
-    { "noexec",     MS_NOEXEC },
-    { "nosuid",     MS_NOSUID },
-    { "nodev",      MS_NODEV },
-    { "nodiratime", MS_NODIRATIME },
-    { "ro",         MS_RDONLY },
-    { "rw",         0 },
-    { "remount",    MS_REMOUNT },
-    { "bind",       MS_BIND },
-    { "rec",        MS_REC },
-    { "unbindable", MS_UNBINDABLE },
-    { "private",    MS_PRIVATE },
-    { "slave",      MS_SLAVE },
-    { "shared",     MS_SHARED },
-    { "defaults",   0 },
-    { 0,            0 },
-};
-
-static struct flag_list fs_mgr_flags[] = {
-    { "wait",        MF_WAIT },
-    { "check",       MF_CHECK },
-    { "encryptable=",MF_CRYPT },
-    { "nonremovable",MF_NONREMOVABLE },
-    { "voldmanaged=",MF_VOLDMANAGED},
-    { "length=",     MF_LENGTH },
-    { "recoveryonly",MF_RECOVERYONLY },
-    { "swapprio=",   MF_SWAPPRIO },
-    { "zramsize=",   MF_ZRAMSIZE },
-    { "verify",      MF_VERIFY },
-    { "noemulatedsd", MF_NOEMULATEDSD },
-    { "defaults",    0 },
-    { 0,             0 },
-};
-
-struct fs_mgr_flag_values {
-    char *key_loc;
-    long long part_length;
-    char *label;
-    int partnum;
-    int swap_prio;
-    unsigned int zram_size;
-};
-
 /*
  * gettime() - returns the time in seconds of the system's monotonic clock or
  * zero on error.
@@ -133,269 +84,6 @@
     return ret;
 }
 
-static int parse_flags(char *flags, struct flag_list *fl,
-                       struct fs_mgr_flag_values *flag_vals,
-                       char *fs_options, int fs_options_len)
-{
-    int f = 0;
-    int i;
-    char *p;
-    char *savep;
-
-    /* initialize flag values.  If we find a relevant flag, we'll
-     * update the value */
-    if (flag_vals) {
-        memset(flag_vals, 0, sizeof(*flag_vals));
-        flag_vals->partnum = -1;
-        flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
-    }
-
-    /* initialize fs_options to the null string */
-    if (fs_options && (fs_options_len > 0)) {
-        fs_options[0] = '\0';
-    }
-
-    p = strtok_r(flags, ",", &savep);
-    while (p) {
-        /* Look for the flag "p" in the flag list "fl"
-         * If not found, the loop exits with fl[i].name being null.
-         */
-        for (i = 0; fl[i].name; i++) {
-            if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
-                f |= fl[i].flag;
-                if ((fl[i].flag == MF_CRYPT) && flag_vals) {
-                    /* The encryptable flag is followed by an = and the
-                     * location of the keys.  Get it and return it.
-                     */
-                    flag_vals->key_loc = strdup(strchr(p, '=') + 1);
-                } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
-                    /* The length flag is followed by an = and the
-                     * size of the partition.  Get it and return it.
-                     */
-                    flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
-                } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
-                    /* The voldmanaged flag is followed by an = and the
-                     * label, a colon and the partition number or the
-                     * word "auto", e.g.
-                     *   voldmanaged=sdcard:3
-                     * Get and return them.
-                     */
-                    char *label_start;
-                    char *label_end;
-                    char *part_start;
-
-                    label_start = strchr(p, '=') + 1;
-                    label_end = strchr(p, ':');
-                    if (label_end) {
-                        flag_vals->label = strndup(label_start,
-                                                   (int) (label_end - label_start));
-                        part_start = strchr(p, ':') + 1;
-                        if (!strcmp(part_start, "auto")) {
-                            flag_vals->partnum = -1;
-                        } else {
-                            flag_vals->partnum = strtol(part_start, NULL, 0);
-                        }
-                    } else {
-                        ERROR("Warning: voldmanaged= flag malformed\n");
-                    }
-                } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
-                    flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
-                } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
-                    flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0);
-                }
-                break;
-            }
-        }
-
-        if (!fl[i].name) {
-            if (fs_options) {
-                /* It's not a known flag, so it must be a filesystem specific
-                 * option.  Add it to fs_options if it was passed in.
-                 */
-                strlcat(fs_options, p, fs_options_len);
-                strlcat(fs_options, ",", fs_options_len);
-            } else {
-                /* fs_options was not passed in, so if the flag is unknown
-                 * it's an error.
-                 */
-                ERROR("Warning: unknown flag %s\n", p);
-            }
-        }
-        p = strtok_r(NULL, ",", &savep);
-    }
-
-out:
-    if (fs_options && fs_options[0]) {
-        /* remove the last trailing comma from the list of options */
-        fs_options[strlen(fs_options) - 1] = '\0';
-    }
-
-    return f;
-}
-
-struct fstab *fs_mgr_read_fstab(const char *fstab_path)
-{
-    FILE *fstab_file;
-    int cnt, entries;
-    ssize_t len;
-    size_t alloc_len = 0;
-    char *line = NULL;
-    const char *delim = " \t";
-    char *save_ptr, *p;
-    struct fstab *fstab = NULL;
-    struct fstab_rec *recs;
-    struct fs_mgr_flag_values flag_vals;
-#define FS_OPTIONS_LEN 1024
-    char tmp_fs_options[FS_OPTIONS_LEN];
-
-    fstab_file = fopen(fstab_path, "r");
-    if (!fstab_file) {
-        ERROR("Cannot open file %s\n", fstab_path);
-        return 0;
-    }
-
-    entries = 0;
-    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
-        /* if the last character is a newline, shorten the string by 1 byte */
-        if (line[len - 1] == '\n') {
-            line[len - 1] = '\0';
-        }
-        /* Skip any leading whitespace */
-        p = line;
-        while (isspace(*p)) {
-            p++;
-        }
-        /* ignore comments or empty lines */
-        if (*p == '#' || *p == '\0')
-            continue;
-        entries++;
-    }
-
-    if (!entries) {
-        ERROR("No entries found in fstab\n");
-        goto err;
-    }
-
-    /* Allocate and init the fstab structure */
-    fstab = calloc(1, sizeof(struct fstab));
-    fstab->num_entries = entries;
-    fstab->fstab_filename = strdup(fstab_path);
-    fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
-
-    fseek(fstab_file, 0, SEEK_SET);
-
-    cnt = 0;
-    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
-        /* if the last character is a newline, shorten the string by 1 byte */
-        if (line[len - 1] == '\n') {
-            line[len - 1] = '\0';
-        }
-
-        /* Skip any leading whitespace */
-        p = line;
-        while (isspace(*p)) {
-            p++;
-        }
-        /* ignore comments or empty lines */
-        if (*p == '#' || *p == '\0')
-            continue;
-
-        /* If a non-comment entry is greater than the size we allocated, give an
-         * error and quit.  This can happen in the unlikely case the file changes
-         * between the two reads.
-         */
-        if (cnt >= entries) {
-            ERROR("Tried to process more entries than counted\n");
-            break;
-        }
-
-        if (!(p = strtok_r(line, delim, &save_ptr))) {
-            ERROR("Error parsing mount source\n");
-            goto err;
-        }
-        fstab->recs[cnt].blk_device = strdup(p);
-
-        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
-            ERROR("Error parsing mount_point\n");
-            goto err;
-        }
-        fstab->recs[cnt].mount_point = strdup(p);
-
-        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
-            ERROR("Error parsing fs_type\n");
-            goto err;
-        }
-        fstab->recs[cnt].fs_type = strdup(p);
-
-        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
-            ERROR("Error parsing mount_flags\n");
-            goto err;
-        }
-        tmp_fs_options[0] = '\0';
-        fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
-                                       tmp_fs_options, FS_OPTIONS_LEN);
-
-        /* fs_options are optional */
-        if (tmp_fs_options[0]) {
-            fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
-        } else {
-            fstab->recs[cnt].fs_options = NULL;
-        }
-
-        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
-            ERROR("Error parsing fs_mgr_options\n");
-            goto err;
-        }
-        fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
-                                                    &flag_vals, NULL, 0);
-        fstab->recs[cnt].key_loc = flag_vals.key_loc;
-        fstab->recs[cnt].length = flag_vals.part_length;
-        fstab->recs[cnt].label = flag_vals.label;
-        fstab->recs[cnt].partnum = flag_vals.partnum;
-        fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
-        fstab->recs[cnt].zram_size = flag_vals.zram_size;
-        cnt++;
-    }
-    fclose(fstab_file);
-    free(line);
-    return fstab;
-
-err:
-    fclose(fstab_file);
-    free(line);
-    if (fstab)
-        fs_mgr_free_fstab(fstab);
-    return NULL;
-}
-
-void fs_mgr_free_fstab(struct fstab *fstab)
-{
-    int i;
-
-    if (!fstab) {
-        return;
-    }
-
-    for (i = 0; i < fstab->num_entries; i++) {
-        /* Free the pointers return by strdup(3) */
-        free(fstab->recs[i].blk_device);
-        free(fstab->recs[i].mount_point);
-        free(fstab->recs[i].fs_type);
-        free(fstab->recs[i].fs_options);
-        free(fstab->recs[i].key_loc);
-        free(fstab->recs[i].label);
-    }
-
-    /* Free the fstab_recs array created by calloc(3) */
-    free(fstab->recs);
-
-    /* Free the fstab filename */
-    free(fstab->fstab_filename);
-
-    /* Free fstab */
-    free(fstab);
-}
-
 static void check_fs(char *blk_device, char *fs_type, char *target)
 {
     int status;
@@ -823,71 +511,3 @@
 
     return 0;
 }
-
-/* Add an entry to the fstab, and return 0 on success or -1 on error */
-int fs_mgr_add_entry(struct fstab *fstab,
-                     const char *mount_point, const char *fs_type,
-                     const char *blk_device, long long length)
-{
-    struct fstab_rec *new_fstab_recs;
-    int n = fstab->num_entries;
-
-    new_fstab_recs = (struct fstab_rec *)
-                     realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
-
-    if (!new_fstab_recs) {
-        return -1;
-    }
-
-    /* A new entry was added, so initialize it */
-     memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
-     new_fstab_recs[n].mount_point = strdup(mount_point);
-     new_fstab_recs[n].fs_type = strdup(fs_type);
-     new_fstab_recs[n].blk_device = strdup(blk_device);
-     new_fstab_recs[n].length = 0;
-
-     /* Update the fstab struct */
-     fstab->recs = new_fstab_recs;
-     fstab->num_entries++;
-
-     return 0;
-}
-
-struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
-{
-    int i;
-
-    if (!fstab) {
-        return NULL;
-    }
-
-    for (i = 0; i < fstab->num_entries; i++) {
-        int len = strlen(fstab->recs[i].mount_point);
-        if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
-            (path[len] == '\0' || path[len] == '/')) {
-            return &fstab->recs[i];
-        }
-    }
-
-    return NULL;
-}
-
-int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
-}
-
-int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_NONREMOVABLE;
-}
-
-int fs_mgr_is_encryptable(struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_CRYPT;
-}
-
-int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
-}
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
new file mode 100644
index 0000000..6145771
--- /dev/null
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -0,0 +1,403 @@
+/*
+ * 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 <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+
+#include "fs_mgr_priv.h"
+
+struct fs_mgr_flag_values {
+    char *key_loc;
+    long long part_length;
+    char *label;
+    int partnum;
+    int swap_prio;
+    unsigned int zram_size;
+};
+
+struct flag_list {
+    const char *name;
+    unsigned flag;
+};
+
+static struct flag_list mount_flags[] = {
+    { "noatime",    MS_NOATIME },
+    { "noexec",     MS_NOEXEC },
+    { "nosuid",     MS_NOSUID },
+    { "nodev",      MS_NODEV },
+    { "nodiratime", MS_NODIRATIME },
+    { "ro",         MS_RDONLY },
+    { "rw",         0 },
+    { "remount",    MS_REMOUNT },
+    { "bind",       MS_BIND },
+    { "rec",        MS_REC },
+    { "unbindable", MS_UNBINDABLE },
+    { "private",    MS_PRIVATE },
+    { "slave",      MS_SLAVE },
+    { "shared",     MS_SHARED },
+    { "defaults",   0 },
+    { 0,            0 },
+};
+
+static struct flag_list fs_mgr_flags[] = {
+    { "wait",        MF_WAIT },
+    { "check",       MF_CHECK },
+    { "encryptable=",MF_CRYPT },
+    { "nonremovable",MF_NONREMOVABLE },
+    { "voldmanaged=",MF_VOLDMANAGED},
+    { "length=",     MF_LENGTH },
+    { "recoveryonly",MF_RECOVERYONLY },
+    { "swapprio=",   MF_SWAPPRIO },
+    { "zramsize=",   MF_ZRAMSIZE },
+    { "verify",      MF_VERIFY },
+    { "noemulatedsd", MF_NOEMULATEDSD },
+    { "defaults",    0 },
+    { 0,             0 },
+};
+
+static int parse_flags(char *flags, struct flag_list *fl,
+                       struct fs_mgr_flag_values *flag_vals,
+                       char *fs_options, int fs_options_len)
+{
+    int f = 0;
+    int i;
+    char *p;
+    char *savep;
+
+    /* initialize flag values.  If we find a relevant flag, we'll
+     * update the value */
+    if (flag_vals) {
+        memset(flag_vals, 0, sizeof(*flag_vals));
+        flag_vals->partnum = -1;
+        flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
+    }
+
+    /* initialize fs_options to the null string */
+    if (fs_options && (fs_options_len > 0)) {
+        fs_options[0] = '\0';
+    }
+
+    p = strtok_r(flags, ",", &savep);
+    while (p) {
+        /* Look for the flag "p" in the flag list "fl"
+         * If not found, the loop exits with fl[i].name being null.
+         */
+        for (i = 0; fl[i].name; i++) {
+            if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
+                f |= fl[i].flag;
+                if ((fl[i].flag == MF_CRYPT) && flag_vals) {
+                    /* The encryptable flag is followed by an = and the
+                     * location of the keys.  Get it and return it.
+                     */
+                    flag_vals->key_loc = strdup(strchr(p, '=') + 1);
+                } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
+                    /* The length flag is followed by an = and the
+                     * size of the partition.  Get it and return it.
+                     */
+                    flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
+                } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
+                    /* The voldmanaged flag is followed by an = and the
+                     * label, a colon and the partition number or the
+                     * word "auto", e.g.
+                     *   voldmanaged=sdcard:3
+                     * Get and return them.
+                     */
+                    char *label_start;
+                    char *label_end;
+                    char *part_start;
+
+                    label_start = strchr(p, '=') + 1;
+                    label_end = strchr(p, ':');
+                    if (label_end) {
+                        flag_vals->label = strndup(label_start,
+                                                   (int) (label_end - label_start));
+                        part_start = strchr(p, ':') + 1;
+                        if (!strcmp(part_start, "auto")) {
+                            flag_vals->partnum = -1;
+                        } else {
+                            flag_vals->partnum = strtol(part_start, NULL, 0);
+                        }
+                    } else {
+                        ERROR("Warning: voldmanaged= flag malformed\n");
+                    }
+                } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
+                    flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
+                } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
+                    flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0);
+                }
+                break;
+            }
+        }
+
+        if (!fl[i].name) {
+            if (fs_options) {
+                /* It's not a known flag, so it must be a filesystem specific
+                 * option.  Add it to fs_options if it was passed in.
+                 */
+                strlcat(fs_options, p, fs_options_len);
+                strlcat(fs_options, ",", fs_options_len);
+            } else {
+                /* fs_options was not passed in, so if the flag is unknown
+                 * it's an error.
+                 */
+                ERROR("Warning: unknown flag %s\n", p);
+            }
+        }
+        p = strtok_r(NULL, ",", &savep);
+    }
+
+out:
+    if (fs_options && fs_options[0]) {
+        /* remove the last trailing comma from the list of options */
+        fs_options[strlen(fs_options) - 1] = '\0';
+    }
+
+    return f;
+}
+
+struct fstab *fs_mgr_read_fstab(const char *fstab_path)
+{
+    FILE *fstab_file;
+    int cnt, entries;
+    ssize_t len;
+    size_t alloc_len = 0;
+    char *line = NULL;
+    const char *delim = " \t";
+    char *save_ptr, *p;
+    struct fstab *fstab = NULL;
+    struct fstab_rec *recs;
+    struct fs_mgr_flag_values flag_vals;
+#define FS_OPTIONS_LEN 1024
+    char tmp_fs_options[FS_OPTIONS_LEN];
+
+    fstab_file = fopen(fstab_path, "r");
+    if (!fstab_file) {
+        ERROR("Cannot open file %s\n", fstab_path);
+        return 0;
+    }
+
+    entries = 0;
+    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
+        /* if the last character is a newline, shorten the string by 1 byte */
+        if (line[len - 1] == '\n') {
+            line[len - 1] = '\0';
+        }
+        /* Skip any leading whitespace */
+        p = line;
+        while (isspace(*p)) {
+            p++;
+        }
+        /* ignore comments or empty lines */
+        if (*p == '#' || *p == '\0')
+            continue;
+        entries++;
+    }
+
+    if (!entries) {
+        ERROR("No entries found in fstab\n");
+        goto err;
+    }
+
+    /* Allocate and init the fstab structure */
+    fstab = calloc(1, sizeof(struct fstab));
+    fstab->num_entries = entries;
+    fstab->fstab_filename = strdup(fstab_path);
+    fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
+
+    fseek(fstab_file, 0, SEEK_SET);
+
+    cnt = 0;
+    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
+        /* if the last character is a newline, shorten the string by 1 byte */
+        if (line[len - 1] == '\n') {
+            line[len - 1] = '\0';
+        }
+
+        /* Skip any leading whitespace */
+        p = line;
+        while (isspace(*p)) {
+            p++;
+        }
+        /* ignore comments or empty lines */
+        if (*p == '#' || *p == '\0')
+            continue;
+
+        /* If a non-comment entry is greater than the size we allocated, give an
+         * error and quit.  This can happen in the unlikely case the file changes
+         * between the two reads.
+         */
+        if (cnt >= entries) {
+            ERROR("Tried to process more entries than counted\n");
+            break;
+        }
+
+        if (!(p = strtok_r(line, delim, &save_ptr))) {
+            ERROR("Error parsing mount source\n");
+            goto err;
+        }
+        fstab->recs[cnt].blk_device = strdup(p);
+
+        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
+            ERROR("Error parsing mount_point\n");
+            goto err;
+        }
+        fstab->recs[cnt].mount_point = strdup(p);
+
+        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
+            ERROR("Error parsing fs_type\n");
+            goto err;
+        }
+        fstab->recs[cnt].fs_type = strdup(p);
+
+        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
+            ERROR("Error parsing mount_flags\n");
+            goto err;
+        }
+        tmp_fs_options[0] = '\0';
+        fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
+                                       tmp_fs_options, FS_OPTIONS_LEN);
+
+        /* fs_options are optional */
+        if (tmp_fs_options[0]) {
+            fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
+        } else {
+            fstab->recs[cnt].fs_options = NULL;
+        }
+
+        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
+            ERROR("Error parsing fs_mgr_options\n");
+            goto err;
+        }
+        fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
+                                                    &flag_vals, NULL, 0);
+        fstab->recs[cnt].key_loc = flag_vals.key_loc;
+        fstab->recs[cnt].length = flag_vals.part_length;
+        fstab->recs[cnt].label = flag_vals.label;
+        fstab->recs[cnt].partnum = flag_vals.partnum;
+        fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
+        fstab->recs[cnt].zram_size = flag_vals.zram_size;
+        cnt++;
+    }
+    fclose(fstab_file);
+    free(line);
+    return fstab;
+
+err:
+    fclose(fstab_file);
+    free(line);
+    if (fstab)
+        fs_mgr_free_fstab(fstab);
+    return NULL;
+}
+
+void fs_mgr_free_fstab(struct fstab *fstab)
+{
+    int i;
+
+    if (!fstab) {
+        return;
+    }
+
+    for (i = 0; i < fstab->num_entries; i++) {
+        /* Free the pointers return by strdup(3) */
+        free(fstab->recs[i].blk_device);
+        free(fstab->recs[i].mount_point);
+        free(fstab->recs[i].fs_type);
+        free(fstab->recs[i].fs_options);
+        free(fstab->recs[i].key_loc);
+        free(fstab->recs[i].label);
+    }
+
+    /* Free the fstab_recs array created by calloc(3) */
+    free(fstab->recs);
+
+    /* Free the fstab filename */
+    free(fstab->fstab_filename);
+
+    /* Free fstab */
+    free(fstab);
+}
+
+/* Add an entry to the fstab, and return 0 on success or -1 on error */
+int fs_mgr_add_entry(struct fstab *fstab,
+                     const char *mount_point, const char *fs_type,
+                     const char *blk_device, long long length)
+{
+    struct fstab_rec *new_fstab_recs;
+    int n = fstab->num_entries;
+
+    new_fstab_recs = (struct fstab_rec *)
+                     realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
+
+    if (!new_fstab_recs) {
+        return -1;
+    }
+
+    /* A new entry was added, so initialize it */
+     memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
+     new_fstab_recs[n].mount_point = strdup(mount_point);
+     new_fstab_recs[n].fs_type = strdup(fs_type);
+     new_fstab_recs[n].blk_device = strdup(blk_device);
+     new_fstab_recs[n].length = 0;
+
+     /* Update the fstab struct */
+     fstab->recs = new_fstab_recs;
+     fstab->num_entries++;
+
+     return 0;
+}
+
+struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
+{
+    int i;
+
+    if (!fstab) {
+        return NULL;
+    }
+
+    for (i = 0; i < fstab->num_entries; i++) {
+        int len = strlen(fstab->recs[i].mount_point);
+        if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
+            (path[len] == '\0' || path[len] == '/')) {
+            return &fstab->recs[i];
+        }
+    }
+
+    return NULL;
+}
+
+int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
+}
+
+int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_NONREMOVABLE;
+}
+
+int fs_mgr_is_encryptable(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_CRYPT;
+}
+
+int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
+}
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index 1549316..40bc2ec 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -36,8 +36,7 @@
 #include "mincrypt/sha.h"
 #include "mincrypt/sha256.h"
 
-#include "ext4_utils.h"
-#include "ext4.h"
+#include "ext4_sb.h"
 
 #include "fs_mgr_priv.h"
 #include "fs_mgr_priv_verity.h"
@@ -122,6 +121,7 @@
 {
     int data_device;
     struct ext4_super_block sb;
+    struct fs_info info = {0};
 
     data_device = open(blk_device, O_RDONLY);
     if (data_device < 0) {
@@ -141,7 +141,7 @@
         return -1;
     }
 
-    ext4_parse_sb(&sb);
+    ext4_parse_sb(&sb, &info);
     *device_size = info.len;
 
     close(data_device);
diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h
index bd4134c..3c3a482 100644
--- a/include/backtrace/Backtrace.h
+++ b/include/backtrace/Backtrace.h
@@ -17,6 +17,7 @@
 #ifndef _BACKTRACE_BACKTRACE_H
 #define _BACKTRACE_BACKTRACE_H
 
+#include <inttypes.h>
 #include <stdint.h>
 
 #include <string>
@@ -25,6 +26,14 @@
 #include <backtrace/backtrace_constants.h>
 #include <backtrace/BacktraceMap.h>
 
+#if __LP64__
+#define PRIPTR "016" PRIxPTR
+typedef uint64_t word_t;
+#else
+#define PRIPTR "08" PRIxPTR
+typedef uint32_t word_t;
+#endif
+
 struct backtrace_frame_data_t {
   size_t num;             // The current fame number.
   uintptr_t pc;           // The absolute pc.
@@ -65,7 +74,7 @@
   virtual const backtrace_map_t* FindMap(uintptr_t pc);
 
   // Read the data at a specific address.
-  virtual bool ReadWord(uintptr_t ptr, uint32_t* out_value) = 0;
+  virtual bool ReadWord(uintptr_t ptr, word_t* out_value) = 0;
 
   // Create a string representing the formatted line of backtrace information
   // for a single frame.
@@ -96,7 +105,7 @@
 protected:
   Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map);
 
-  virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value);
+  virtual bool VerifyReadWordArgs(uintptr_t ptr, word_t* out_value);
 
   bool BuildMap();
 
diff --git a/include/cutils/debugger.h b/include/cutils/debugger.h
index 4eda523..af80e2c 100644
--- a/include/cutils/debugger.h
+++ b/include/cutils/debugger.h
@@ -23,7 +23,11 @@
 extern "C" {
 #endif
 
+#if __LP64__
+#define DEBUGGER_SOCKET_NAME "android:debuggerd64"
+#else
 #define DEBUGGER_SOCKET_NAME "android:debuggerd"
+#endif
 
 typedef enum {
     // dump a crash
diff --git a/include/cutils/misc.h b/include/cutils/misc.h
index 2c48dfa..0de505f 100644
--- a/include/cutils/misc.h
+++ b/include/cutils/misc.h
@@ -28,13 +28,6 @@
          */
 extern void *load_file(const char *fn, unsigned *sz);
 
-        /* Connects your process to the system debugger daemon
-         * so that on a crash it may be logged or interactively
-         * debugged (depending on system settings).
-         */
-extern void debuggerd_connect(void);
-
-
         /* This is the range of UIDs (and GIDs) that are reserved
          * for assigning to applications.
          */
diff --git a/init/property_service.c b/init/property_service.c
index 6cb2c7b..4af0c17 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -24,6 +24,7 @@
 #include <dirent.h>
 #include <limits.h>
 #include <errno.h>
+#include <sys/poll.h>
 
 #include <cutils/misc.h>
 #include <cutils/sockets.h>
@@ -367,6 +368,9 @@
     socklen_t addr_size = sizeof(addr);
     socklen_t cr_size = sizeof(cr);
     char * source_ctx = NULL;
+    struct pollfd ufds[1];
+    const int timeout_ms = 2 * 1000;  /* Default 2 sec timeout for caller to send property. */
+    int nr;
 
     if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
         return;
@@ -379,7 +383,21 @@
         return;
     }
 
-    r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0));
+    ufds[0].fd = s;
+    ufds[0].events = POLLIN;
+    ufds[0].revents = 0;
+    nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms));
+    if (nr == 0) {
+        ERROR("sys_prop: timeout waiting for uid=%d to send property message.\n", cr.uid);
+        close(s);
+        return;
+    } else if (nr < 0) {
+        ERROR("sys_prop: error waiting for uid=%d to send property message. err=%d %s\n", cr.uid, errno, strerror(errno));
+        close(s);
+        return;
+    }
+
+    r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), MSG_DONTWAIT));
     if(r != sizeof(prop_msg)) {
         ERROR("sys_prop: mis-match msg size received: %d expected: %zu errno: %d\n",
               r, sizeof(prop_msg), errno);
@@ -521,7 +539,7 @@
                     || (sb.st_uid != 0)
                     || (sb.st_gid != 0)
                     || (sb.st_nlink != 1)) {
-                ERROR("skipping insecure property file %s (uid=%u gid=%u nlink=%d mode=%o)\n",
+                ERROR("skipping insecure property file %s (uid=%lu gid=%lu nlink=%d mode=%o)\n",
                       entry->d_name, sb.st_uid, sb.st_gid, sb.st_nlink, sb.st_mode);
                 close(fd);
                 continue;
diff --git a/libbacktrace/Android.build.mk b/libbacktrace/Android.build.mk
new file mode 100644
index 0000000..3c80cc2
--- /dev/null
+++ b/libbacktrace/Android.build.mk
@@ -0,0 +1,73 @@
+#
+# 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 $(CLEAR_VARS)
+
+LOCAL_MODULE := $(module)
+LOCAL_MODULE_TAGS := $(module_tag)
+
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+    $(LOCAL_PATH)/Android.mk \
+    $(LOCAL_PATH)/Android.build.mk \
+
+LOCAL_CFLAGS := \
+    $(common_cflags) \
+    $($(module)_cflags) \
+    $($(module)_cflags_$(build_type)) \
+
+LOCAL_CONLYFLAGS += \
+    $(common_conlyflags) \
+    $($(module)_conlyflags) \
+    $($(module)_conlyflags_$(build_type)) \
+
+LOCAL_CPPFLAGS += \
+    $(common_cppflags) \
+    $($(module)_cppflags) \
+    $($(module)_cppflags_$(build_type)) \
+
+LOCAL_C_INCLUDES := \
+    $(common_c_includes) \
+    $($(module)_c_includes) \
+    $($(module)_c_includes_$(build_type)) \
+
+LOCAL_SRC_FILES := \
+    $($(module)_src_files) \
+    $($(module)_src_files_$(build_type)) \
+
+LOCAL_STATIC_LIBRARIES := \
+    $($(module)_static_libraries) \
+    $($(module)_static_libraries_$(build_type)) \
+
+LOCAL_SHARED_LIBRARIES := \
+    $($(module)_shared_libraries) \
+    $($(module)_shared_libraries_$(build_type)) \
+
+LOCAL_LDLIBS := \
+    $($(module)_ldlibs) \
+    $($(module)_ldlibs_$(build_type)) \
+
+ifeq ($(build_type),target)
+  include external/stlport/libstlport.mk
+
+  include $(BUILD_$(build_target))
+endif
+
+ifeq ($(build_type),host)
+  # Only build if host builds are supported.
+  ifeq ($(build_host),true)
+    include $(BUILD_HOST_$(build_target))
+  endif
+endif
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
old mode 100644
new mode 100755
index 0ae8839..33af0a3
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -1,14 +1,23 @@
-LOCAL_PATH:= $(call my-dir)
+#
+# 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.
+#
 
-common_src := \
-	BacktraceImpl.cpp \
-	BacktraceMap.cpp \
-	BacktraceThread.cpp \
-	thread_utils.c \
+LOCAL_PATH:= $(call my-dir)
 
 common_cflags := \
 	-Wall \
-	-Wno-unused-parameter \
 	-Werror \
 
 common_conlyflags := \
@@ -17,274 +26,148 @@
 common_cppflags := \
 	-std=gnu++11 \
 
-common_shared_libs := \
+build_host := false
+ifeq ($(HOST_OS),linux)
+ifeq ($(HOST_ARCH),$(filter $(HOST_ARCH),x86 x86_64))
+build_host := true
+endif
+endif
+
+#-------------------------------------------------------------------------
+# The libbacktrace library.
+#-------------------------------------------------------------------------
+libbacktrace_src_files := \
+	BacktraceImpl.cpp \
+	BacktraceMap.cpp \
+	BacktraceThread.cpp \
+	thread_utils.c \
+
+libbacktrace_shared_libraries_target := \
 	libcutils \
 	libgccdemangle \
-	liblog \
 
 # To enable using libunwind on each arch, add it to this list.
-libunwind_architectures := arm arm64
+libunwind_architectures := arm arm64 x86 x86_64
 
 ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),$(libunwind_architectures)))
-
-#----------------------------------------------------------------------------
-# The native libbacktrace library with libunwind.
-#----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	$(common_src) \
+libbacktrace_src_files += \
 	UnwindCurrent.cpp \
 	UnwindMap.cpp \
 	UnwindPtrace.cpp \
 
-LOCAL_CFLAGS := \
-	$(common_cflags) \
-
-LOCAL_CONLYFLAGS += \
-	$(common_conlyflags) \
-
-LOCAL_CPPFLAGS += \
-	$(common_cppflags) \
-
-LOCAL_MODULE := libbacktrace
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_C_INCLUDES := \
-	$(common_c_includes) \
+libbacktrace_c_includes := \
 	external/libunwind/include \
 
-LOCAL_SHARED_LIBRARIES := \
-	$(common_shared_libs) \
+libbacktrace_shared_libraries := \
 	libunwind \
 	libunwind-ptrace \
 
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-	$(LOCAL_PATH)/Android.mk
-
-include external/stlport/libstlport.mk
-
-include $(BUILD_SHARED_LIBRARY)
-
-else
-
-#----------------------------------------------------------------------------
-# The native libbacktrace library with libcorkscrew.
-#----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	$(common_src) \
-	Corkscrew.cpp \
-
-LOCAL_CFLAGS := \
-	$(common_cflags) \
-
-LOCAL_CONLYFLAGS += \
-	$(common_conlyflags) \
-
-LOCAL_CPPFLAGS += \
-	$(common_cppflags) \
-
-LOCAL_MODULE := libbacktrace
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_C_INCLUDES := \
-	$(common_c_includes) \
-	system/core/libcorkscrew \
-
-LOCAL_SHARED_LIBRARIES := \
-	$(common_shared_libs) \
-	libcorkscrew \
-	libdl \
-
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-	$(LOCAL_PATH)/Android.mk
-
-include external/stlport/libstlport.mk
-
-include $(BUILD_SHARED_LIBRARY)
-
-endif
-
-#----------------------------------------------------------------------------
-# libbacktrace test library, all optimizations turned off
-#----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbacktrace_test
-LOCAL_MODULE_FLAGS := debug
-
-LOCAL_SRC_FILES := \
-	backtrace_testlib.c
-
-LOCAL_CFLAGS += \
-	-std=gnu99 \
-	-O0 \
-
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-	$(LOCAL_PATH)/Android.mk
-
-include $(BUILD_SHARED_LIBRARY)
-
-#----------------------------------------------------------------------------
-# libbacktrace test executable
-#----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := backtrace_test
-LOCAL_MODULE_FLAGS := debug
-
-LOCAL_SRC_FILES := \
-	backtrace_test.cpp \
-	thread_utils.c \
-
-LOCAL_CFLAGS += \
-	$(common_cflags) \
-	-fno-builtin \
-	-fstack-protector-all \
-	-O0 \
-	-g \
-	-DGTEST_OS_LINUX_ANDROID \
-	-DGTEST_HAS_STD_STRING \
-
-ifeq ($(TARGET_ARCH),arm64)
-  $(info TODO: $(LOCAL_PATH)/Android.mk -fstack-protector not yet available for the AArch64 toolchain)
-  LOCAL_CFLAGS += -fno-stack-protector
-endif # arm64
-
-LOCAL_CONLYFLAGS += \
-	$(common_conlyflags) \
-
-LOCAL_CPPFLAGS += \
-	$(common_cppflags) \
-
-LOCAL_SHARED_LIBRARIES += \
-	libcutils \
-	libbacktrace_test \
-	libbacktrace \
-
-LOCAL_LDLIBS := \
-	-lpthread \
-
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-	$(LOCAL_PATH)/Android.mk
-
-include $(BUILD_NATIVE_TEST)
-
-#----------------------------------------------------------------------------
-# Only x86 host versions of libbacktrace supported.
-#----------------------------------------------------------------------------
-ifeq ($(HOST_ARCH),x86)
-
-#----------------------------------------------------------------------------
-# The host libbacktrace library using libcorkscrew
-#----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-
-
-LOCAL_CFLAGS += \
-	$(common_cflags) \
-
-LOCAL_CONLYFLAGS += \
-	$(common_conlyflags) \
-
-LOCAL_C_INCLUDES := \
-	$(common_c_includes) \
-
-LOCAL_SHARED_LIBRARIES := \
-	libgccdemangle \
+libbacktrace_shared_libraries_host := \
 	liblog \
 
-LOCAL_MODULE := libbacktrace
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-	$(LOCAL_PATH)/Android.mk
-
-ifeq ($(HOST_OS),linux)
-LOCAL_SRC_FILES += \
-	$(common_src) \
-	Corkscrew.cpp \
-
-LOCAL_C_INCLUDES += \
-	system/core/libcorkscrew \
-
-LOCAL_SHARED_LIBRARIES := \
-	libcorkscrew \
-
-LOCAL_CPPFLAGS += \
-	$(common_cppflags) \
-
-LOCAL_LDLIBS += \
-	-ldl \
-	-lrt \
+libbacktrace_static_libraries_host := \
+	libcutils \
 
 else
-LOCAL_SRC_FILES += \
-	BacktraceMap.cpp \
+libbacktrace_src_files += \
+	Corkscrew.cpp \
+
+libbacktrace_c_includes := \
+	system/core/libcorkscrew \
+
+libbacktrace_shared_libraries := \
+	libcorkscrew \
+
+libbacktrace_shared_libraries_target += \
+	libdl \
+
+libbacktrace_ldlibs_host := \
+	-ldl \
 
 endif
 
-include $(BUILD_HOST_SHARED_LIBRARY)
+module := libbacktrace
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(LOCAL_PATH)/Android.build.mk
+build_type := host
+include $(LOCAL_PATH)/Android.build.mk
 
-#----------------------------------------------------------------------------
-# The host test is only supported on linux.
-#----------------------------------------------------------------------------
-ifeq ($(HOST_OS),linux)
-
-#----------------------------------------------------------------------------
-# libbacktrace host test library, all optimizations turned off
-#----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbacktrace_test
-LOCAL_MODULE_FLAGS := debug
-
-LOCAL_SRC_FILES := \
-	backtrace_testlib.c
-
-LOCAL_CFLAGS += \
-	-std=gnu99 \
+#-------------------------------------------------------------------------
+# The libbacktrace_test library needed by backtrace_test.
+#-------------------------------------------------------------------------
+libbacktrace_test_cflags := \
 	-O0 \
 
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-	$(LOCAL_PATH)/Android.mk
+libbacktrace_test_src_files := \
+	backtrace_testlib.c \
 
-include $(BUILD_HOST_SHARED_LIBRARY)
+module := libbacktrace_test
+module_tag := debug
+build_type := target
+build_target := SHARED_LIBRARY
+include $(LOCAL_PATH)/Android.build.mk
+build_type := host
+include $(LOCAL_PATH)/Android.build.mk
 
-#----------------------------------------------------------------------------
-# libbacktrace host test executable
-#----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := backtrace_test
-LOCAL_MODULE_FLAGS := debug
-
-LOCAL_SRC_FILES := \
-	backtrace_test.cpp \
-	thread_utils.c \
-
-LOCAL_CFLAGS += \
-	$(common_cflags) \
+#-------------------------------------------------------------------------
+# The backtrace_test executable.
+#-------------------------------------------------------------------------
+backtrace_test_cflags := \
 	-fno-builtin \
-	-fstack-protector-all \
 	-O0 \
 	-g \
 	-DGTEST_HAS_STD_STRING \
 
-LOCAL_SHARED_LIBRARIES := \
+ifneq ($(TARGET_ARCH),arm64)
+backtrace_test_cflags += -fstack-protector-all
+else
+  $(info TODO: $(LOCAL_PATH)/Android.mk -fstack-protector not yet available for the AArch64 toolchain)
+  common_cflags += -fno-stack-protector
+endif # arm64
+
+backtrace_test_cflags_target := \
+	-DGTEST_OS_LINUX_ANDROID \
+
+backtrace_test_src_files := \
+	backtrace_test.cpp \
+	thread_utils.c \
+
+backtrace_test_ldlibs := \
+	-lpthread \
+
+backtrace_test_ldlibs_host := \
+	-lrt \
+
+backtrace_test_shared_libraries := \
 	libbacktrace_test \
 	libbacktrace \
 
-LOCAL_LDLIBS := \
-	-lpthread \
+backtrace_test_shared_libraries_target := \
+	libcutils \
 
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-	$(LOCAL_PATH)/Android.mk
+module := backtrace_test
+module_tag := debug
+build_type := target
+build_target := NATIVE_TEST
+include $(LOCAL_PATH)/Android.build.mk
+build_type := host
+include $(LOCAL_PATH)/Android.build.mk
 
-include $(BUILD_HOST_NATIVE_TEST)
+#----------------------------------------------------------------------------
+# Special truncated libbacktrace library for mac.
+#----------------------------------------------------------------------------
+ifeq ($(HOST_OS),darwin)
 
-endif # HOST_OS == linux
+include $(CLEAR_VARS)
 
-endif # HOST_ARCH == x86
+LOCAL_MODULE := libbacktrace
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+	BacktraceMap.cpp \
+
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+endif # HOST_OS-darwin
diff --git a/libbacktrace/BacktraceImpl.cpp b/libbacktrace/BacktraceImpl.cpp
index 39296b4..855810e 100644
--- a/libbacktrace/BacktraceImpl.cpp
+++ b/libbacktrace/BacktraceImpl.cpp
@@ -21,9 +21,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-
 #include <string>
 
 #include <backtrace/Backtrace.h>
@@ -82,10 +79,10 @@
   return func_name;
 }
 
-bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value) {
-  if (ptr & 3) {
+bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) {
+  if (ptr & (sizeof(word_t)-1)) {
     BACK_LOGW("invalid pointer %p", (void*)ptr);
-    *out_value = (uint32_t)-1;
+    *out_value = (word_t)-1;
     return false;
   }
   return true;
@@ -143,18 +140,18 @@
 BacktraceCurrent::~BacktraceCurrent() {
 }
 
-bool BacktraceCurrent::ReadWord(uintptr_t ptr, uint32_t* out_value) {
+bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) {
   if (!VerifyReadWordArgs(ptr, out_value)) {
     return false;
   }
 
   const backtrace_map_t* map = FindMap(ptr);
   if (map && map->flags & PROT_READ) {
-    *out_value = *reinterpret_cast<uint32_t*>(ptr);
+    *out_value = *reinterpret_cast<word_t*>(ptr);
     return true;
   } else {
     BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr));
-    *out_value = static_cast<uint32_t>(-1);
+    *out_value = static_cast<word_t>(-1);
     return false;
   }
 }
@@ -171,7 +168,7 @@
 BacktracePtrace::~BacktracePtrace() {
 }
 
-bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) {
+bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
   if (!VerifyReadWordArgs(ptr, out_value)) {
     return false;
   }
@@ -184,7 +181,7 @@
   // 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<uint32_t>(-1) && errno) {
+  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));
     return false;
diff --git a/libbacktrace/BacktraceImpl.h b/libbacktrace/BacktraceImpl.h
old mode 100644
new mode 100755
index af014d5..48dd11c
--- a/libbacktrace/BacktraceImpl.h
+++ b/libbacktrace/BacktraceImpl.h
@@ -61,7 +61,7 @@
   BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map);
   virtual ~BacktraceCurrent();
 
-  bool ReadWord(uintptr_t ptr, uint32_t* out_value);
+  bool ReadWord(uintptr_t ptr, word_t* out_value);
 };
 
 class BacktracePtrace : public Backtrace {
@@ -69,7 +69,7 @@
   BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map);
   virtual ~BacktracePtrace();
 
-  bool ReadWord(uintptr_t ptr, uint32_t* out_value);
+  bool ReadWord(uintptr_t ptr, word_t* out_value);
 };
 
 Backtrace* CreateCurrentObj(BacktraceMap* map);
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
old mode 100644
new mode 100755
index 17b71b9..81e69bb
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "libbacktrace"
 
+#include <sys/ucontext.h>
 #include <sys/types.h>
 
 #include <backtrace/Backtrace.h>
@@ -27,27 +28,6 @@
 #include "UnwindCurrent.h"
 #include "UnwindMap.h"
 
-// Define the ucontext_t structures needed for each supported arch.
-#if defined(__arm__)
-  // The current version of the <signal.h> doesn't define ucontext_t.
-  #include <asm/sigcontext.h> // Ensure 'struct sigcontext' is defined.
-
-  // Machine context at the time a signal was raised.
-  typedef struct ucontext {
-    uint32_t uc_flags;
-    struct ucontext* uc_link;
-    stack_t uc_stack;
-    struct sigcontext uc_mcontext;
-    uint32_t uc_sigmask;
-  } ucontext_t;
-#elif defined(__i386__)
-  #include <asm/sigcontext.h>
-  #include <asm/ucontext.h>
-  typedef struct ucontext ucontext_t;
-#elif !defined(__mips__) && !defined(__aarch64__)
-  #error Unsupported architecture.
-#endif
-
 //-------------------------------------------------------------------------
 // UnwindCurrent functions.
 //-------------------------------------------------------------------------
@@ -158,7 +138,7 @@
   context->regs[13] = uc->uc_mcontext.arm_sp;
   context->regs[14] = uc->uc_mcontext.arm_lr;
   context->regs[15] = uc->uc_mcontext.arm_pc;
-#elif defined(__mips__) || defined(__i386__)
+#else
   context->uc_mcontext = uc->uc_mcontext;
 #endif
 }
diff --git a/libbacktrace/UnwindMap.cpp b/libbacktrace/UnwindMap.cpp
index 03bb192..8268db6 100644
--- a/libbacktrace/UnwindMap.cpp
+++ b/libbacktrace/UnwindMap.cpp
@@ -45,7 +45,7 @@
     pthread_mutex_lock(&g_map_mutex);
     if (--g_map_references == 0) {
       // Clear the local address space map.
-      unw_map_set(unw_local_addr_space, NULL);
+      unw_map_local_set(NULL);
       unw_map_cursor_destroy(&map_cursor_);
     }
     pthread_mutex_unlock(&g_map_mutex);
@@ -61,8 +61,8 @@
     if (g_map_references == 0) {
       return_value = (unw_map_cursor_create(&map_cursor_, pid_) == 0);
       if (return_value) {
-        // Set the local address space to this cursor map.
-        unw_map_set(unw_local_addr_space, &map_cursor_);
+        // Set the local address space map to our new map.
+        unw_map_local_set(&map_cursor_);
         g_map_references = 1;
         g_map_cursor = map_cursor_;
       }
diff --git a/libcorkscrew/Android.mk b/libcorkscrew/Android.mk
index e275317..8f3b68c 100644
--- a/libcorkscrew/Android.mk
+++ b/libcorkscrew/Android.mk
@@ -30,6 +30,8 @@
 	arch-x86/backtrace-x86.c \
 	arch-x86/ptrace-x86.c
 
+ifneq ($(TARGET_IS_64_BIT),true)
+
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(generic_src_files)
@@ -66,9 +68,9 @@
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_EXECUTABLE)
 
+endif # TARGET_IS_64_BIT == false
 
-# TODO: reenable darwin-x86
-# ifeq ($(HOST_ARCH),x86)
+
 ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
 
 # Build libcorkscrew.
@@ -95,4 +97,4 @@
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_HOST_EXECUTABLE)
 
-endif # HOST_ARCH == x86
+endif # $(HOST_OS)-$(HOST_ARCH) == linux-x86
diff --git a/libcorkscrew/arch-arm/backtrace-arm.c b/libcorkscrew/arch-arm/backtrace-arm.c
index 7bd0d8f..751efbf 100644
--- a/libcorkscrew/arch-arm/backtrace-arm.c
+++ b/libcorkscrew/arch-arm/backtrace-arm.c
@@ -62,19 +62,7 @@
 #include <elf.h>
 #include <cutils/log.h>
 
-#if !defined(__BIONIC_HAVE_UCONTEXT_T)
-/* Old versions of the Android <signal.h> didn't define ucontext_t. */
-#include <asm/sigcontext.h> /* Ensure 'struct sigcontext' is defined. */
-
-/* Machine context at the time a signal was raised. */
-typedef struct ucontext {
-    uint32_t uc_flags;
-    struct ucontext* uc_link;
-    stack_t uc_stack;
-    struct sigcontext uc_mcontext;
-    uint32_t uc_sigmask;
-} ucontext_t;
-#endif /* !__BIONIC_HAVE_UCONTEXT_T */
+#include <ucontext.h>
 
 /* Unwind state. */
 typedef struct {
diff --git a/libcorkscrew/arch-mips/backtrace-mips.c b/libcorkscrew/arch-mips/backtrace-mips.c
index 57cb324..832fb86 100644
--- a/libcorkscrew/arch-mips/backtrace-mips.c
+++ b/libcorkscrew/arch-mips/backtrace-mips.c
@@ -36,18 +36,7 @@
 #include <sys/ptrace.h>
 #include <cutils/log.h>
 
-#if defined(__BIONIC__)
-
-#if defined(__BIONIC_HAVE_UCONTEXT_T)
-
-// Bionic offers the Linux kernel headers.
-#include <asm/sigcontext.h>
-#include <asm/ucontext.h>
-typedef struct ucontext ucontext_t;
-
-#else /* __BIONIC_HAVE_UCONTEXT_T */
-
-/* Old versions of the Android <signal.h> didn't define ucontext_t. */
+#include <sys/ucontext.h>
 
 /* For PTRACE_GETREGS */
 typedef struct {
@@ -71,30 +60,6 @@
     REG_GP, REG_SP, REG_S8, REG_RA,
 };
 
-/* Machine context at the time a signal was raised. */
-typedef struct ucontext {
-    unsigned int sc_regmask;
-    unsigned int sc_status;
-    unsigned long long sc_pc;
-    unsigned long long sc_regs[32];
-    unsigned long long sc_fpregs[32];
-    unsigned int sc_acx;
-    unsigned int sc_fpc_csr;
-    unsigned int sc_fpc_eir;
-    unsigned int sc_used_math;
-    unsigned int sc_dsp;
-    unsigned long long sc_mdhi;
-    unsigned long long sc_mdlo;
-    unsigned long sc_hi1;
-    unsigned long sc_lo1;
-    unsigned long sc_hi2;
-    unsigned long sc_lo2;
-    unsigned long sc_hi3;
-    unsigned long sc_lo3;
-} ucontext_t;
-
-#endif /* __BIONIC_HAVE_UCONTEXT_T */
-#endif
 
 /* Unwind state. */
 typedef struct {
@@ -896,10 +861,10 @@
     const ucontext_t* uc = (const ucontext_t*)sigcontext;
 
     unwind_state_t state;
-    state.reg[DWARF_PC] = uc->sc_pc;
-    state.reg[DWARF_RA] = uc->sc_regs[REG_RA];
-    state.reg[DWARF_FP] = uc->sc_regs[REG_S8];
-    state.reg[DWARF_SP] = uc->sc_regs[REG_SP];
+    state.reg[DWARF_PC] = uc->uc_mcontext.pc;
+    state.reg[DWARF_RA] = uc->uc_mcontext.gregs[REG_RA];
+    state.reg[DWARF_FP] = uc->uc_mcontext.gregs[REG_S8];
+    state.reg[DWARF_SP] = uc->uc_mcontext.gregs[REG_SP];
 
     ALOGV("unwind_backtrace_signal_arch: "
           "ignore_depth=%d max_depth=%d pc=0x%08x sp=0x%08x ra=0x%08x\n",
diff --git a/libcorkscrew/arch-x86/backtrace-x86.c b/libcorkscrew/arch-x86/backtrace-x86.c
index ef22821..df486de 100755
--- a/libcorkscrew/arch-x86/backtrace-x86.c
+++ b/libcorkscrew/arch-x86/backtrace-x86.c
@@ -36,46 +36,7 @@
 #include <sys/ptrace.h>
 #include <cutils/log.h>
 
-#if defined(__BIONIC__)
-
-#if defined(__BIONIC_HAVE_UCONTEXT_T)
-
-// Bionic offers the Linux kernel headers.
-#include <asm/sigcontext.h>
-#include <asm/ucontext.h>
-typedef struct ucontext ucontext_t;
-
-#else /* __BIONIC_HAVE_UCONTEXT_T */
-
-/* Old versions of the Android <signal.h> didn't define ucontext_t. */
-
-typedef struct {
-  uint32_t  gregs[32];
-  void*     fpregs;
-  uint32_t  oldmask;
-  uint32_t  cr2;
-} mcontext_t;
-
-enum {
-  REG_GS = 0, REG_FS, REG_ES, REG_DS,
-  REG_EDI, REG_ESI, REG_EBP, REG_ESP,
-  REG_EBX, REG_EDX, REG_ECX, REG_EAX,
-  REG_TRAPNO, REG_ERR, REG_EIP, REG_CS,
-  REG_EFL, REG_UESP, REG_SS
-};
-
-/* Machine context at the time a signal was raised. */
-typedef struct ucontext {
-    uint32_t uc_flags;
-    struct ucontext* uc_link;
-    stack_t uc_stack;
-    mcontext_t uc_mcontext;
-    uint32_t uc_sigmask;
-} ucontext_t;
-
-#endif /* __BIONIC_HAVE_UCONTEXT_T */
-
-#elif defined(__APPLE__)
+#if defined(__APPLE__)
 
 #define _XOPEN_SOURCE
 #include <ucontext.h>
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index 3625d93..d3ce8f5 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -1,10 +1,11 @@
 #include <alloca.h>
 #include <errno.h>
-#include <sys/socket.h>
-#include <sys/types.h>
 #include <pthread.h>
+#include <signal.h>
 #include <string.h>
 #include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 
 #define LOG_TAG "SocketClient"
 #include <cutils/log.h>
@@ -43,8 +44,7 @@
     }
 }
 
-SocketClient::~SocketClient()
-{
+SocketClient::~SocketClient() {
     if (mSocketOwned) {
         close(mSocket);
     }
@@ -180,10 +180,19 @@
         return 0;
     }
 
+    int ret = 0;
+    int e = 0; // SLOGW and sigaction are not inert regarding errno
     int current = 0;
 
+    struct sigaction new_action, old_action;
+    memset(&new_action, 0, sizeof(new_action));
+    new_action.sa_handler = SIG_IGN;
+    sigaction(SIGPIPE, &new_action, &old_action);
+
     for (;;) {
-        ssize_t rc = writev(mSocket, iov + current, iovcnt - current);
+        ssize_t rc = TEMP_FAILURE_RETRY(
+            writev(mSocket, iov + current, iovcnt - current));
+
         if (rc > 0) {
             size_t written = rc;
             while ((current < iovcnt) && (written >= iov[current].iov_len)) {
@@ -198,18 +207,21 @@
             continue;
         }
 
-        if (rc < 0 && errno == EINTR)
-            continue;
-
         if (rc == 0) {
+            e = EIO;
             SLOGW("0 length write :(");
-            errno = EIO;
         } else {
-            SLOGW("write error (%s)", strerror(errno));
+            e = errno;
+            SLOGW("write error (%s)", strerror(e));
         }
-        return -1;
+        ret = -1;
+        break;
     }
-    return 0;
+
+    sigaction(SIGPIPE, &old_action, &new_action);
+
+    errno = e;
+    return ret;
 }
 
 void SocketClient::incRef() {