Merge "Add libkeyutils."
diff --git a/adb/Android.mk b/adb/Android.mk
index dc87bb0..4d7d487 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -15,11 +15,11 @@
     -Wno-unused-parameter \
     -Wno-missing-field-initializers \
     -Wvla \
-    -DADB_VERSION="\"$(tool_version)\""
+    -DADB_VERSION="\"$(tool_version)\"" \
 
 ADB_COMMON_posix_CFLAGS := \
     -Wexit-time-destructors \
-    -Wthread-safety
+    -Wthread-safety \
 
 ADB_COMMON_linux_CFLAGS := \
     $(ADB_COMMON_posix_CFLAGS) \
@@ -232,7 +232,7 @@
     libcutils \
     libdiagnose_usb \
     libmdnssd \
-    libgmock_host
+    libgmock_host \
 
 LOCAL_STATIC_LIBRARIES_linux := libusb
 LOCAL_STATIC_LIBRARIES_darwin := libusb
@@ -300,7 +300,7 @@
     libcrypto \
     libdiagnose_usb \
     liblog \
-    libmdnssd
+    libmdnssd \
 
 # Don't use libcutils on Windows.
 LOCAL_STATIC_LIBRARIES_darwin := libcutils
diff --git a/adb/adb.cpp b/adb/adb.cpp
index c1e0d98..23f6580 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1054,15 +1054,12 @@
     if (strcmp(service, "kill") == 0) {
         fprintf(stderr, "adb server killed by remote request\n");
         fflush(stdout);
+
+        // Send a reply even though we don't read it anymore, so that old versions
+        // of adb that do read it don't spew error messages.
         SendOkay(reply_fd);
 
-        // On Windows, if the process exits with open sockets that
-        // shutdown(SD_SEND) has not been called on, TCP RST segments will be
-        // sent to the peers which will cause their next recv() to error-out
-        // with WSAECONNRESET. In the case of this code, that means the client
-        // may not read the OKAY sent above.
-        adb_shutdown(reply_fd);
-
+        // Rely on process exit to close the socket for us.
         android::base::quick_exit(0);
     }
 
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 4f3ff25..f5d0f02 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -123,7 +123,7 @@
     return false;
 }
 
-int _adb_connect(const std::string& service, std::string* error) {
+static int _adb_connect(const std::string& service, std::string* error) {
     D("_adb_connect: %s", service.c_str());
     if (service.empty() || service.size() > MAX_PAYLOAD_V1) {
         *error = android::base::StringPrintf("bad service name length (%zd)",
@@ -158,6 +158,25 @@
     return fd;
 }
 
+bool adb_kill_server() {
+    D("adb_kill_server");
+    std::string reason;
+    int fd = socket_spec_connect(__adb_server_socket_spec, &reason);
+    if (fd < 0) {
+        fprintf(stderr, "cannot connect to daemon at %s: %s\n", __adb_server_socket_spec,
+                reason.c_str());
+        return true;
+    }
+
+    if (!SendProtocolString(fd, "host:kill")) {
+        fprintf(stderr, "error: write failure during connection: %s\n", strerror(errno));
+        return false;
+    }
+
+    ReadOrderlyShutdown(fd);
+    return true;
+}
+
 int adb_connect(const std::string& service, std::string* error) {
     // first query the adb server's version
     int fd = _adb_connect("host:version", error);
@@ -214,18 +233,7 @@
         if (version != ADB_SERVER_VERSION) {
             fprintf(stderr, "adb server version (%d) doesn't match this client (%d); killing...\n",
                     version, ADB_SERVER_VERSION);
-            fd = _adb_connect("host:kill", error);
-            if (fd >= 0) {
-                ReadOrderlyShutdown(fd);
-                adb_close(fd);
-            } else {
-                // If we couldn't connect to the server or had some other error,
-                // report it, but still try to start the server.
-                fprintf(stderr, "error: %s\n", error->c_str());
-            }
-
-            /* XXX can we better detect its death? */
-            std::this_thread::sleep_for(2s);
+            adb_kill_server();
             goto start_server;
         }
     }
diff --git a/adb/adb_client.h b/adb/adb_client.h
index d07c1e9..fabec00 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -26,7 +26,9 @@
 // Connect to adb, connect to the named service, and return a valid fd for
 // interacting with that service upon success or a negative number on failure.
 int adb_connect(const std::string& service, std::string* _Nonnull error);
-int _adb_connect(const std::string& service, std::string* _Nonnull error);
+
+// Kill the currently running adb server, if it exists.
+bool adb_kill_server();
 
 // Connect to adb, connect to the named service, returns true if the connection
 // succeeded AND the service returned OKAY. Outputs any returned error otherwise.
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index 18b1492..30cb29b 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -19,8 +19,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <algorithm>
+#include <list>
+
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
 #include <cutils/sockets.h>
 
 #include "socket_spec.h"
@@ -64,8 +68,9 @@
 
 // listener_list retains ownership of all created alistener objects. Removing an alistener from
 // this list will cause it to be deleted.
+static auto& listener_list_mutex = *new std::mutex();
 typedef std::list<std::unique_ptr<alistener>> ListenerList;
-static ListenerList& listener_list = *new ListenerList();
+static ListenerList& listener_list GUARDED_BY(listener_list_mutex) = *new ListenerList();
 
 static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
     if (ev & FDE_READ) {
@@ -108,7 +113,8 @@
 }
 
 // Called as a transport disconnect function. |arg| is the raw alistener*.
-static void listener_disconnect(void* arg, atransport*) {
+static void listener_disconnect(void* arg, atransport*) EXCLUDES(listener_list_mutex) {
+    std::lock_guard<std::mutex> lock(listener_list_mutex);
     for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) {
         if (iter->get() == arg) {
             (*iter)->transport = nullptr;
@@ -119,7 +125,8 @@
 }
 
 // Write the list of current listeners (network redirections) into a string.
-std::string format_listeners() {
+std::string format_listeners() EXCLUDES(listener_list_mutex) {
+    std::lock_guard<std::mutex> lock(listener_list_mutex);
     std::string result;
     for (auto& l : listener_list) {
         // Ignore special listeners like those for *smartsocket*
@@ -135,7 +142,9 @@
     return result;
 }
 
-InstallStatus remove_listener(const char* local_name, atransport* transport) {
+InstallStatus remove_listener(const char* local_name, atransport* transport)
+    EXCLUDES(listener_list_mutex) {
+    std::lock_guard<std::mutex> lock(listener_list_mutex);
     for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) {
         if (local_name == (*iter)->local_name) {
             listener_list.erase(iter);
@@ -145,7 +154,8 @@
     return INSTALL_STATUS_LISTENER_NOT_FOUND;
 }
 
-void remove_all_listeners() {
+void remove_all_listeners() EXCLUDES(listener_list_mutex) {
+    std::lock_guard<std::mutex> lock(listener_list_mutex);
     auto iter = listener_list.begin();
     while (iter != listener_list.end()) {
         // Never remove smart sockets.
@@ -157,9 +167,18 @@
     }
 }
 
+void close_smartsockets() EXCLUDES(listener_list_mutex) {
+    std::lock_guard<std::mutex> lock(listener_list_mutex);
+    auto pred = [](const std::unique_ptr<alistener>& listener) {
+        return listener->local_name == "*smartsocket*";
+    };
+    listener_list.erase(std::remove_if(listener_list.begin(), listener_list.end(), pred));
+}
+
 InstallStatus install_listener(const std::string& local_name, const char* connect_to,
                                atransport* transport, int no_rebind, int* resolved_tcp_port,
-                               std::string* error) {
+                               std::string* error) EXCLUDES(listener_list_mutex) {
+    std::lock_guard<std::mutex> lock(listener_list_mutex);
     for (auto& l : listener_list) {
         if (local_name == l->local_name) {
             // Can't repurpose a smartsocket.
@@ -212,7 +231,7 @@
 
     if (transport) {
         listener->disconnect.opaque = listener.get();
-        listener->disconnect.func   = listener_disconnect;
+        listener->disconnect.func = listener_disconnect;
         transport->AddDisconnect(&listener->disconnect);
     }
 
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index 8eba00a..70a2ee1 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -41,4 +41,6 @@
 InstallStatus remove_listener(const char* local_name, atransport* transport);
 void remove_all_listeners(void);
 
+void close_smartsockets();
+
 #endif /* __ADB_LISTENERS_H */
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index fe5099c..bd9ad01 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -92,6 +92,16 @@
 }
 #endif
 
+void adb_server_cleanup() {
+    // Upon exit, we want to clean up in the following order:
+    //   1. close_smartsockets, so that we don't get any new clients
+    //   2. kick_all_transports, to avoid writing only part of a packet to a transport.
+    //   3. usb_cleanup, to tear down the USB stack.
+    close_smartsockets();
+    kick_all_transports();
+    usb_cleanup();
+}
+
 int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) {
 #if defined(_WIN32)
     // adb start-server starts us up with stdout and stderr hooked up to
@@ -111,12 +121,13 @@
     SetConsoleCtrlHandler(ctrlc_handler, TRUE);
 #else
     signal(SIGINT, [](int) {
-        android::base::quick_exit(0);
+        fdevent_run_on_main_thread([]() { android::base::quick_exit(0); });
     });
 #endif
 
-    init_transport_registration();
+    android::base::at_quick_exit(adb_server_cleanup);
 
+    init_transport_registration();
     init_mdns_transport_discovery();
 
     usb_init();
diff --git a/adb/client/usb_dispatch.cpp b/adb/client/usb_dispatch.cpp
index 710a3ce..ce57731 100644
--- a/adb/client/usb_dispatch.cpp
+++ b/adb/client/usb_dispatch.cpp
@@ -27,6 +27,14 @@
     }
 }
 
+void usb_cleanup() {
+    if (should_use_libusb()) {
+        libusb::usb_cleanup();
+    } else {
+        native::usb_cleanup();
+    }
+}
+
 int usb_write(usb_handle* h, const void* data, int len) {
     return should_use_libusb()
                ? libusb::usb_write(reinterpret_cast<libusb::usb_handle*>(h), data, len)
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 15d4b7a..18a8ff2 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -152,7 +152,9 @@
 static auto& usb_handles_mutex = *new std::mutex();
 
 static std::thread* device_poll_thread = nullptr;
-static std::atomic<bool> terminate_device_poll_thread(false);
+static bool terminate_device_poll_thread = false;
+static auto& device_poll_mutex = *new std::mutex();
+static auto& device_poll_cv = *new std::condition_variable();
 
 static std::string get_device_address(libusb_device* device) {
     return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
@@ -376,7 +378,7 @@
 static void poll_for_devices() {
     libusb_device** list;
     adb_thread_setname("device poll");
-    while (!terminate_device_poll_thread) {
+    while (true) {
         const ssize_t device_count = libusb_get_device_list(nullptr, &list);
 
         LOG(VERBOSE) << "found " << device_count << " attached devices";
@@ -389,7 +391,10 @@
 
         adb_notify_device_scan_complete();
 
-        std::this_thread::sleep_for(500ms);
+        std::unique_lock<std::mutex> lock(device_poll_mutex);
+        if (device_poll_cv.wait_for(lock, 500ms, []() { return terminate_device_poll_thread; })) {
+            return;
+        }
     }
 }
 
@@ -410,11 +415,21 @@
 
     // Spawn a thread to do device enumeration.
     // TODO: Use libusb_hotplug_* instead?
+    std::unique_lock<std::mutex> lock(device_poll_mutex);
     device_poll_thread = new std::thread(poll_for_devices);
-    android::base::at_quick_exit([]() {
+}
+
+void usb_cleanup() {
+    {
+        std::unique_lock<std::mutex> lock(device_poll_mutex);
         terminate_device_poll_thread = true;
-        device_poll_thread->join();
-    });
+
+        if (!device_poll_thread) {
+            return;
+        }
+    }
+    device_poll_cv.notify_all();
+    device_poll_thread->join();
 }
 
 // Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index f9ba7cb..a7df0ed 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -598,4 +598,7 @@
 
     std::thread(device_poll_thread).detach();
 }
+
+void usb_cleanup() {}
+
 } // namespace native
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index e366754..4e1480f 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -430,7 +430,7 @@
     VLOG(USB) << "RunLoopThread done";
 }
 
-static void usb_cleanup() NO_THREAD_SAFETY_ANALYSIS {
+void usb_cleanup() NO_THREAD_SAFETY_ANALYSIS {
     VLOG(USB) << "usb_cleanup";
     // Wait until usb operations in RunLoopThread finish, and prevent further operations.
     operate_device_lock.lock();
@@ -440,8 +440,6 @@
 void usb_init() {
     static bool initialized = false;
     if (!initialized) {
-        atexit(usb_cleanup);
-
         usb_inited_flag = false;
 
         std::thread(RunLoopThread).detach();
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index ec55b0e..1620e6e 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -265,6 +265,8 @@
   std::thread(_power_notification_thread).detach();
 }
 
+void usb_cleanup() {}
+
 usb_handle* do_usb_open(const wchar_t* interface_name) {
   unsigned long name_len = 0;
 
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index a9b1540..f49c69d 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -1546,25 +1546,7 @@
         return 0;
     }
     else if (!strcmp(argv[0], "kill-server")) {
-        std::string error;
-        int fd = _adb_connect("host:kill", &error);
-        if (fd == -2) {
-            // Failed to make network connection to server. Don't output the
-            // network error since that is expected.
-            fprintf(stderr,"* server not running *\n");
-            // Successful exit code because the server is already "killed".
-            return 0;
-        } else if (fd == -1) {
-            // Some other error.
-            fprintf(stderr, "error: %s\n", error.c_str());
-            return 1;
-        } else {
-            // Successfully connected, kill command sent, okay status came back.
-            // Server should exit() in a moment, if not already.
-            ReadOrderlyShutdown(fd);
-            adb_close(fd);
-            return 0;
-        }
+        return adb_kill_server() ? 0 : 1;
     }
     else if (!strcmp(argv[0], "sideload")) {
         if (argc != 2) return syntax_error("sideload requires an argument");
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 20de642..13cfaa1 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -568,15 +568,14 @@
                     transport_registration_func, 0);
 
     fdevent_set(&transport_registration_fde, FDE_READ);
-#if ADB_HOST
-    android::base::at_quick_exit([]() {
-        // To avoid only writing part of a packet to a transport after exit, kick all transports.
-        std::lock_guard<std::mutex> lock(transport_lock);
-        for (auto t : transport_list) {
-            t->Kick();
-        }
-    });
-#endif
+}
+
+void kick_all_transports() {
+    // To avoid only writing part of a packet to a transport after exit, kick all transports.
+    std::lock_guard<std::mutex> lock(transport_lock);
+    for (auto t : transport_list) {
+        t->Kick();
+    }
 }
 
 /* the fdevent select pump is single threaded */
diff --git a/adb/transport.h b/adb/transport.h
index e129355..006aaf4 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -207,6 +207,7 @@
 std::string list_transports(bool long_listing);
 atransport* find_transport(const char* serial);
 void kick_all_tcp_devices();
+void kick_all_transports();
 
 void register_usb_transport(usb_handle* h, const char* serial,
                             const char* devpath, unsigned writeable);
diff --git a/adb/usb.h b/adb/usb.h
index e867ec8..f428ede 100644
--- a/adb/usb.h
+++ b/adb/usb.h
@@ -22,6 +22,7 @@
 
 #define ADB_USB_INTERFACE(handle_ref_type)                       \
     void usb_init();                                             \
+    void usb_cleanup();                                          \
     int usb_write(handle_ref_type h, const void* data, int len); \
     int usb_read(handle_ref_type h, void* data, int len);        \
     int usb_close(handle_ref_type h);                            \
diff --git a/debuggerd/libdebuggerd/arm/machine.cpp b/debuggerd/libdebuggerd/arm/machine.cpp
index 78c2306..ac833ae 100644
--- a/debuggerd/libdebuggerd/arm/machine.cpp
+++ b/debuggerd/libdebuggerd/arm/machine.cpp
@@ -48,6 +48,21 @@
   }
 }
 
+#define DUMP_GP_REGISTERS(log, reg_prefix)                                             \
+  _LOG(log, logtype::REGISTERS, "    r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r0), static_cast<uint32_t>(reg_prefix##r1),   \
+       static_cast<uint32_t>(reg_prefix##r2), static_cast<uint32_t>(reg_prefix##r3));  \
+  _LOG(log, logtype::REGISTERS, "    r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r4), static_cast<uint32_t>(reg_prefix##r5),   \
+       static_cast<uint32_t>(reg_prefix##r6), static_cast<uint32_t>(reg_prefix##r7));  \
+  _LOG(log, logtype::REGISTERS, "    r8 %08x  r9 %08x  sl %08x  fp %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r8), static_cast<uint32_t>(reg_prefix##r9),   \
+       static_cast<uint32_t>(reg_prefix##r10), static_cast<uint32_t>(reg_prefix##fp)); \
+  _LOG(log, logtype::REGISTERS, "    ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n", \
+       static_cast<uint32_t>(reg_prefix##ip), static_cast<uint32_t>(reg_prefix##sp),   \
+       static_cast<uint32_t>(reg_prefix##lr), static_cast<uint32_t>(reg_prefix##pc),   \
+       static_cast<uint32_t>(reg_prefix##cpsr))
+
 void dump_registers(log_t* log, pid_t tid) {
   pt_regs r;
   if (ptrace(PTRACE_GETREGS, tid, 0, &r)) {
@@ -55,19 +70,7 @@
     return;
   }
 
-  _LOG(log, logtype::REGISTERS, "    r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
-       static_cast<uint32_t>(r.ARM_r0), static_cast<uint32_t>(r.ARM_r1),
-       static_cast<uint32_t>(r.ARM_r2), static_cast<uint32_t>(r.ARM_r3));
-  _LOG(log, logtype::REGISTERS, "    r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
-       static_cast<uint32_t>(r.ARM_r4), static_cast<uint32_t>(r.ARM_r5),
-       static_cast<uint32_t>(r.ARM_r6), static_cast<uint32_t>(r.ARM_r7));
-  _LOG(log, logtype::REGISTERS, "    r8 %08x  r9 %08x  sl %08x  fp %08x\n",
-       static_cast<uint32_t>(r.ARM_r8), static_cast<uint32_t>(r.ARM_r9),
-       static_cast<uint32_t>(r.ARM_r10), static_cast<uint32_t>(r.ARM_fp));
-  _LOG(log, logtype::REGISTERS, "    ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",
-       static_cast<uint32_t>(r.ARM_ip), static_cast<uint32_t>(r.ARM_sp),
-       static_cast<uint32_t>(r.ARM_lr), static_cast<uint32_t>(r.ARM_pc),
-       static_cast<uint32_t>(r.ARM_cpsr));
+  DUMP_GP_REGISTERS(log, r.ARM_);
 
   user_vfp vfp_regs;
   if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
@@ -81,3 +84,7 @@
   }
   _LOG(log, logtype::FP_REGISTERS, "    scr %08lx\n", vfp_regs.fpscr);
 }
+
+void dump_registers(log_t* log, const ucontext_t* uc) {
+  DUMP_GP_REGISTERS(log, uc->uc_mcontext.arm_);
+}
diff --git a/debuggerd/libdebuggerd/arm64/machine.cpp b/debuggerd/libdebuggerd/arm64/machine.cpp
index e7bf79a..fa73c99a 100644
--- a/debuggerd/libdebuggerd/arm64/machine.cpp
+++ b/debuggerd/libdebuggerd/arm64/machine.cpp
@@ -52,6 +52,17 @@
   }
 }
 
+#define DUMP_GP_REGISTERS(log)                                                                   \
+  for (int i = 0; i < 28; i += 4) {                                                              \
+    const char* fmt = "    x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx\n";    \
+    _LOG(log, logtype::REGISTERS, fmt, i, r.regs[i], i + 1, r.regs[i + 1], i + 2, r.regs[i + 2], \
+         i + 3, r.regs[i + 3]);                                                                  \
+  }                                                                                              \
+  _LOG(log, logtype::REGISTERS, "    x28  %016llx  x29  %016llx  x30  %016llx\n", r.regs[28],    \
+       r.regs[29], r.regs[30]);                                                                  \
+  _LOG(log, logtype::REGISTERS, "    sp   %016llx  pc   %016llx  pstate %016llx\n", r.sp, r.pc,  \
+       r.pstate)
+
 void dump_registers(log_t* log, pid_t tid) {
   struct user_pt_regs r;
   struct iovec io;
@@ -63,20 +74,7 @@
     return;
   }
 
-  for (int i = 0; i < 28; i += 4) {
-    _LOG(log, logtype::REGISTERS,
-         "    x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx\n",
-         i, r.regs[i],
-         i+1, r.regs[i+1],
-         i+2, r.regs[i+2],
-         i+3, r.regs[i+3]);
-  }
-
-  _LOG(log, logtype::REGISTERS, "    x28  %016llx  x29  %016llx  x30  %016llx\n",
-       r.regs[28], r.regs[29], r.regs[30]);
-
-  _LOG(log, logtype::REGISTERS, "    sp   %016llx  pc   %016llx  pstate %016llx\n",
-       r.sp, r.pc, r.pstate);
+  DUMP_GP_REGISTERS(log);
 
   struct user_fpsimd_state f;
   io.iov_base = &f;
@@ -99,3 +97,8 @@
   }
   _LOG(log, logtype::FP_REGISTERS, "    fpsr %08x  fpcr %08x\n", f.fpsr, f.fpcr);
 }
+
+void dump_registers(log_t* log, const ucontext_t* ucontext) {
+  const mcontext_t& r = ucontext->uc_mcontext;
+  DUMP_GP_REGISTERS(log);
+}
diff --git a/debuggerd/libdebuggerd/include/machine.h b/debuggerd/libdebuggerd/include/machine.h
index e65b147..5e56682 100644
--- a/debuggerd/libdebuggerd/include/machine.h
+++ b/debuggerd/libdebuggerd/include/machine.h
@@ -25,5 +25,6 @@
 
 void dump_memory_and_code(log_t* log, Backtrace* backtrace);
 void dump_registers(log_t* log, pid_t tid);
+void dump_registers(log_t* log, const ucontext_t* uc);
 
 #endif // _DEBUGGERD_MACHINE_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 0c38449..edc7be5 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -470,6 +470,11 @@
   }
 }
 
+// Weak noop implementation, real implementations are in <arch>/machine.cpp.
+__attribute__((weak)) void dump_registers(log_t* log, const ucontext_t*) {
+  _LOG(log, logtype::REGISTERS, "    register dumping unimplemented on this architecture");
+}
+
 static void dump_thread(log_t* log, pid_t pid, pid_t tid, const std::string& process_name,
                         const std::string& thread_name, BacktraceMap* map,
                         uintptr_t abort_msg_address, bool primary_thread) {
@@ -749,11 +754,15 @@
   read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>");
   read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
 
+  _LOG(&log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
+  dump_header_info(&log);
   dump_thread_info(&log, pid, tid, thread_name, process_name);
   dump_signal_info(&log, siginfo);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid));
   dump_abort_message(backtrace.get(), &log, abort_msg_address);
+  dump_registers(&log, ucontext);
+
   // TODO: Dump registers from the ucontext.
   if (backtrace->Unwind(0, ucontext)) {
     dump_backtrace_and_stack(backtrace.get(), &log);
diff --git a/init/Android.mk b/init/Android.mk
index 78a4882..617a809 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -61,6 +61,8 @@
 endif
 
 include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
 LOCAL_CPPFLAGS := $(init_cflags)
 LOCAL_SRC_FILES:= \
     action.cpp \
@@ -82,6 +84,8 @@
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
 LOCAL_CPPFLAGS := $(init_cflags)
 LOCAL_SRC_FILES:= \
     bootchart.cpp \
@@ -140,6 +144,8 @@
 # Unit tests.
 # =========================================================
 include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
 LOCAL_MODULE := init_tests
 LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_SRC_FILES := \
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
new file mode 100644
index 0000000..ab9e26f
--- /dev/null
+++ b/libvndksupport/Android.bp
@@ -0,0 +1,15 @@
+subdirs = ["tests"]
+
+cc_library_shared {
+    name: "libvndksupport",
+    srcs: ["linker.c"],
+    local_include_dirs: ["include/vndksupport"],
+    export_include_dirs: ["include"],
+    shared_libs: ["liblog"],
+}
+
+llndk_library {
+    name: "libvndksupport",
+    symbol_file: "libvndksupport.map.txt",
+    export_include_dirs: ["include"],
+}
diff --git a/libvndksupport/include/vndksupport/linker.h b/libvndksupport/include/vndksupport/linker.h
new file mode 100644
index 0000000..f509564
--- /dev/null
+++ b/libvndksupport/include/vndksupport/linker.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef VNDKSUPPORT_LINKER_H_
+#define VNDKSUPPORT_LINKER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void* android_load_sphal_library(const char* name, int flag);
+
+int android_unload_sphal_library(void* handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // VNDKSUPPORT_LINKER_H_
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
new file mode 100644
index 0000000..16e38da
--- /dev/null
+++ b/libvndksupport/libvndksupport.map.txt
@@ -0,0 +1,7 @@
+LIBVNDKSUPPORT {
+  global:
+    android_load_sphal_library; # vndk
+    android_unload_sphal_library; # vndk
+  local:
+    *;
+};
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
new file mode 100644
index 0000000..d82307b
--- /dev/null
+++ b/libvndksupport/linker.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 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 "linker.h"
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+
+#define LOG_TAG "vndksupport"
+#include <log/log.h>
+
+extern struct android_namespace_t* android_get_exported_namespace(const char*);
+
+void* android_load_sphal_library(const char* name, int flag) {
+    struct android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
+    if (sphal_namespace != NULL) {
+        const android_dlextinfo dlextinfo = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = sphal_namespace,
+        };
+        void* handle = android_dlopen_ext(name, flag, &dlextinfo);
+        if (handle) {
+            return handle;
+        } else {
+            ALOGW(
+                "Could not load %s from sphal namespace: %s. "
+                "Falling back to loading it from the current namespace,",
+                name, dlerror());
+        }
+    } else {
+        ALOGI(
+            "sphal namespace is not configured for this process. "
+            "Loading %s from the current namespace instead.",
+            name);
+    }
+    return dlopen(name, flag);
+}
+
+int android_unload_sphal_library(void* handle) {
+    return dlclose(handle);
+}
diff --git a/libvndksupport/tests/Android.bp b/libvndksupport/tests/Android.bp
new file mode 100644
index 0000000..3587cf8
--- /dev/null
+++ b/libvndksupport/tests/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2017 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.
+
+cc_test {
+    name: "libvndksupport-tests",
+    srcs: [
+        "linker_test.cpp",
+    ],
+
+    host_supported: false,
+    shared_libs: [
+        "libvndksupport",
+        "libbase",
+    ]
+}
diff --git a/libvndksupport/tests/linker_test.cpp b/libvndksupport/tests/linker_test.cpp
new file mode 100644
index 0000000..7ce27d4
--- /dev/null
+++ b/libvndksupport/tests/linker_test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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 <gtest/gtest.h>
+
+#include <android-base/strings.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <vndksupport/linker.h>
+#include <string>
+
+// Since the test executable will be in /data and ld.config.txt does not
+// configure sphal namespace for executables in /data, the call to
+// android_load_sphal_library will always fallback to the plain dlopen from the
+// default namespace.
+
+// Let's use libEGL_<chipset>.so as a SP-HAL in test
+static std::string find_sphal_lib() {
+    const char* path =
+#if defined(__LP64__)
+        "/vendor/lib64/egl";
+#else
+        "/vendor/lib/egl";
+#endif
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
+
+    dirent* dp;
+    while ((dp = readdir(dir.get())) != nullptr) {
+        std::string name = dp->d_name;
+        if (android::base::StartsWith(name, "libEGL_")) {
+            return std::string(path) + "/" + name;
+        }
+    }
+    return "";
+}
+
+TEST(linker, load_existing_lib) {
+    std::string name = find_sphal_lib();
+    ASSERT_NE("", name);
+    void* handle = android_load_sphal_library(name.c_str(), RTLD_NOW | RTLD_LOCAL);
+    ASSERT_NE(nullptr, handle);
+    android_unload_sphal_library(handle);
+}
+
+TEST(linker, load_nonexisting_lib) {
+    void* handle = android_load_sphal_library("libNeverUseThisName.so", RTLD_NOW | RTLD_LOCAL);
+    ASSERT_EQ(nullptr, handle);
+}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 5f9f799..a4545af 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -60,7 +60,7 @@
 namespace.sphal.links = default,vndk,rs
 
 # WARNING: only NDK libs can be listed here.
-namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so
+namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libvndksupport.so
 
 # WARNING: only VNDK-SP libs can be listed here. DO NOT EDIT this line.
 namespace.sphal.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
@@ -81,7 +81,7 @@
 namespace.rs.permitted.paths = /vendor/${LIB}:/data
 
 namespace.rs.links = default,vndk
-namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so
+namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so:libvndksupport.so
 namespace.rs.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
 
 ###############################################################################
@@ -100,7 +100,7 @@
 # to the default namespace. This is possible since their ABI is stable across
 # Android releases.
 namespace.vndk.links = default
-namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so
+namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libvndksupport.so
 
 
 [vendor]