Merge "Documented adb install --instant"
diff --git a/adb/Android.bp b/adb/Android.bp
index 46bc02b..99de54e 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -222,7 +222,6 @@
 
 cc_binary_host {
     name: "adb",
-    tags: ["debug"],
 
     defaults: ["adb_defaults"],
 
@@ -369,6 +368,7 @@
         "libusb",
         "libmdnssd",
     ],
+    test_suites: ["device-tests"],
 }
 
 python_binary_host {
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 4fbfafb..3bf281c 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -132,6 +132,7 @@
 {
     D("adb: online");
     t->online = 1;
+    t->SetConnectionEstablished(true);
 }
 
 void handle_offline(atransport *t)
@@ -1221,7 +1222,7 @@
     std::string error;
     atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
     if (!t) {
-        return SendFail(reply_fd, error);
+        return -1;
     }
 
     int ret = handle_forward_request(service, t, reply_fd);
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 3bb433d..32bf029 100644
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -21,9 +21,11 @@
 """
 from __future__ import print_function
 
+import binascii
 import contextlib
 import os
 import random
+import select
 import socket
 import struct
 import subprocess
@@ -33,6 +35,68 @@
 import adb
 
 
+@contextlib.contextmanager
+def fake_adb_server(protocol=socket.AF_INET, port=0):
+    """Creates a fake ADB server that just replies with a CNXN packet."""
+
+    serversock = socket.socket(protocol, socket.SOCK_STREAM)
+    if protocol == socket.AF_INET:
+        serversock.bind(('127.0.0.1', port))
+    else:
+        serversock.bind(('::1', port))
+    serversock.listen(1)
+
+    # A pipe that is used to signal the thread that it should terminate.
+    readpipe, writepipe = os.pipe()
+
+    def _adb_packet(command, arg0, arg1, data):
+        bin_command = struct.unpack('I', command)[0]
+        buf = struct.pack('IIIIII', bin_command, arg0, arg1, len(data), 0,
+                          bin_command ^ 0xffffffff)
+        buf += data
+        return buf
+
+    def _handle():
+        rlist = [readpipe, serversock]
+        cnxn_sent = {}
+        while True:
+            ready, _, _ = select.select(rlist, [], [])
+            for r in ready:
+                if r == readpipe:
+                    # Closure pipe
+                    os.close(r)
+                    serversock.shutdown(socket.SHUT_RDWR)
+                    serversock.close()
+                    return
+                elif r == serversock:
+                    # Server socket
+                    conn, _ = r.accept()
+                    rlist.append(conn)
+                else:
+                    # Client socket
+                    data = r.recv(1024)
+                    if not data:
+                        if r in cnxn_sent:
+                            del cnxn_sent[r]
+                        rlist.remove(r)
+                        continue
+                    if r in cnxn_sent:
+                        continue
+                    cnxn_sent[r] = True
+                    r.sendall(_adb_packet('CNXN', 0x01000001, 1024 * 1024,
+                                          'device::ro.product.name=fakeadb'))
+
+    port = serversock.getsockname()[1]
+    server_thread = threading.Thread(target=_handle)
+    server_thread.start()
+
+    try:
+        yield port
+    finally:
+        os.close(writepipe)
+        server_thread.join()
+
+
 class NonApiTest(unittest.TestCase):
     """Tests for ADB that aren't a part of the AndroidDevice API."""
 
@@ -211,45 +275,32 @@
 
         Bug: http://b/30313466
         """
-        ipv4 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        ipv4.bind(('127.0.0.1', 0))
-        ipv4.listen(1)
+        for protocol in (socket.AF_INET, socket.AF_INET6):
+            try:
+                with fake_adb_server(protocol=protocol) as port:
+                    output = subprocess.check_output(
+                        ['adb', 'connect', 'localhost:{}'.format(port)])
 
-        ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
-        try:
-            ipv6.bind(('::1', ipv4.getsockname()[1] + 1))
-            ipv6.listen(1)
-        except socket.error:
-            print("IPv6 not available, skipping")
-            return
+                    self.assertEqual(
+                        output.strip(), 'connected to localhost:{}'.format(port))
+            except socket.error:
+                print("IPv6 not available, skipping")
+                continue
 
-        for s in (ipv4, ipv6):
-            port = s.getsockname()[1]
+    def test_already_connected(self):
+        with fake_adb_server() as port:
             output = subprocess.check_output(
                 ['adb', 'connect', 'localhost:{}'.format(port)])
 
             self.assertEqual(
                 output.strip(), 'connected to localhost:{}'.format(port))
-            s.close()
 
-    def test_already_connected(self):
-        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        s.bind(('127.0.0.1', 0))
-        s.listen(2)
+            # b/31250450: this always returns 0 but probably shouldn't.
+            output = subprocess.check_output(
+                ['adb', 'connect', 'localhost:{}'.format(port)])
 
-        port = s.getsockname()[1]
-        output = subprocess.check_output(
-            ['adb', 'connect', 'localhost:{}'.format(port)])
-
-        self.assertEqual(
-            output.strip(), 'connected to localhost:{}'.format(port))
-
-        # b/31250450: this always returns 0 but probably shouldn't.
-        output = subprocess.check_output(
-            ['adb', 'connect', 'localhost:{}'.format(port)])
-
-        self.assertEqual(
-            output.strip(), 'already connected to localhost:{}'.format(port))
+            self.assertEqual(
+                output.strip(), 'already connected to localhost:{}'.format(port))
 
 def main():
     random.seed(0)
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 92c52e2..fa7cc8c 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -64,6 +64,21 @@
 const char* const kFeatureLibusb = "libusb";
 const char* const kFeaturePushSync = "push_sync";
 
+namespace {
+
+// A class that helps the Clang Thread Safety Analysis deal with
+// std::unique_lock. Given that std::unique_lock is movable, and the analysis
+// can not currently perform alias analysis, it is not annotated. In order to
+// assert that the mutex is held, a ScopedAssumeLocked can be created just after
+// the std::unique_lock.
+class SCOPED_CAPABILITY ScopedAssumeLocked {
+  public:
+    ScopedAssumeLocked(std::mutex& mutex) ACQUIRE(mutex) {}
+    ~ScopedAssumeLocked() RELEASE() {}
+};
+
+}  // namespace
+
 TransportId NextTransportId() {
     static std::atomic<TransportId> next(1);
     return next++;
@@ -77,8 +92,6 @@
     Stop();
 }
 
-static void AssumeLocked(std::mutex& mutex) ASSERT_CAPABILITY(mutex) {}
-
 void BlockingConnectionAdapter::Start() {
     std::lock_guard<std::mutex> lock(mutex_);
     if (started_) {
@@ -103,12 +116,11 @@
         LOG(INFO) << this->transport_name_ << ": write thread spawning";
         while (true) {
             std::unique_lock<std::mutex> lock(mutex_);
+            ScopedAssumeLocked assume_locked(mutex_);
             cv_.wait(lock, [this]() REQUIRES(mutex_) {
                 return this->stopped_ || !this->write_queue_.empty();
             });
 
-            AssumeLocked(mutex_);
-
             if (this->stopped_) {
                 return;
             }
@@ -505,8 +517,8 @@
     if (t->GetConnectionState() != kCsNoPerm) {
         /* initial references are the two threads */
         t->ref_count = 1;
-        t->connection->SetTransportName(t->serial_name());
-        t->connection->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
+        t->connection()->SetTransportName(t->serial_name());
+        t->connection()->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
             if (!check_header(p.get(), t)) {
                 D("%s: remote read: bad header", t->serial);
                 return false;
@@ -519,7 +531,7 @@
             fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
             return true;
         });
-        t->connection->SetErrorCallback([t](Connection*, const std::string& error) {
+        t->connection()->SetErrorCallback([t](Connection*, const std::string& error) {
             D("%s: connection terminated: %s", t->serial, error.c_str());
             fdevent_run_on_main_thread([t]() {
                 handle_offline(t);
@@ -527,7 +539,7 @@
             });
         });
 
-        t->connection->Start();
+        t->connection()->Start();
 #if ADB_HOST
         send_connect(t);
 #endif
@@ -596,7 +608,7 @@
     t->ref_count--;
     if (t->ref_count == 0) {
         D("transport: %s unref (kicking and closing)", t->serial);
-        t->connection->Stop();
+        t->connection()->Stop();
         remove_transport(t);
     } else {
         D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
@@ -721,15 +733,39 @@
     return result;
 }
 
+bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
+    std::unique_lock<std::mutex> lock(mutex_);
+    ScopedAssumeLocked assume_locked(mutex_);
+    return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
+        return connection_established_ready_;
+    }) && connection_established_;
+}
+
+void ConnectionWaitable::SetConnectionEstablished(bool success) {
+    {
+        std::lock_guard<std::mutex> lock(mutex_);
+        if (connection_established_ready_) return;
+        connection_established_ready_ = true;
+        connection_established_ = success;
+        D("connection established with %d", success);
+    }
+    cv_.notify_one();
+}
+
+atransport::~atransport() {
+    // If the connection callback had not been run before, run it now.
+    SetConnectionEstablished(false);
+}
+
 int atransport::Write(apacket* p) {
-    return this->connection->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
+    return this->connection()->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
 }
 
 void atransport::Kick() {
     if (!kicked_) {
         D("kicking transport %s", this->serial);
         kicked_ = true;
-        this->connection->Stop();
+        this->connection()->Stop();
     }
 }
 
@@ -742,6 +778,11 @@
     connection_state_ = state;
 }
 
+void atransport::SetConnection(std::unique_ptr<Connection> connection) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    connection_ = std::shared_ptr<Connection>(std::move(connection));
+}
+
 std::string atransport::connection_state_name() const {
     ConnectionState state = GetConnectionState();
     switch (state) {
@@ -873,6 +914,10 @@
            qual_match(target.c_str(), "device:", device, false);
 }
 
+void atransport::SetConnectionEstablished(bool success) {
+    connection_waitable_->SetConnectionEstablished(success);
+}
+
 #if ADB_HOST
 
 // We use newline as our delimiter, make sure to never output it.
@@ -974,7 +1019,7 @@
             VLOG(TRANSPORT) << "socket transport " << transport->serial
                             << " is already in pending_list and fails to register";
             delete t;
-            return -1;
+            return -EALREADY;
         }
     }
 
@@ -983,7 +1028,7 @@
             VLOG(TRANSPORT) << "socket transport " << transport->serial
                             << " is already in transport_list and fails to register";
             delete t;
-            return -1;
+            return -EALREADY;
         }
     }
 
@@ -992,8 +1037,15 @@
 
     lock.unlock();
 
+    auto waitable = t->connection_waitable();
     register_transport(t);
-    return 0;
+
+    if (local == 1) {
+        // Do not wait for emulator transports.
+        return 0;
+    }
+
+    return waitable->WaitForConnection(std::chrono::seconds(10)) ? 0 : -1;
 }
 
 #if ADB_HOST
@@ -1052,8 +1104,9 @@
 void unregister_usb_transport(usb_handle* usb) {
     std::lock_guard<std::recursive_mutex> lock(transport_lock);
     transport_list.remove_if([usb](atransport* t) {
-        if (auto connection = dynamic_cast<UsbConnection*>(t->connection.get())) {
-            return connection->handle_ == usb && t->GetConnectionState() == kCsNoPerm;
+        auto connection = t->connection();
+        if (auto usb_connection = dynamic_cast<UsbConnection*>(connection.get())) {
+            return usb_connection->handle_ == usb && t->GetConnectionState() == kCsNoPerm;
         }
         return false;
     });
diff --git a/adb/transport.h b/adb/transport.h
index d18c362..ebc186b 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 
 #include <atomic>
+#include <chrono>
 #include <condition_variable>
 #include <deque>
 #include <functional>
@@ -30,6 +31,7 @@
 #include <thread>
 #include <unordered_set>
 
+#include <android-base/macros.h>
 #include <android-base/thread_annotations.h>
 #include <openssl/rsa.h>
 
@@ -160,6 +162,35 @@
     usb_handle* handle_;
 };
 
+// Waits for a transport's connection to be not pending. This is a separate
+// object so that the transport can be destroyed and another thread can be
+// notified of it in a race-free way.
+class ConnectionWaitable {
+  public:
+    ConnectionWaitable() = default;
+    ~ConnectionWaitable() = default;
+
+    // Waits until the first CNXN packet has been received by the owning
+    // atransport, or the specified timeout has elapsed. Can be called from any
+    // thread.
+    //
+    // Returns true if the CNXN packet was received in a timely fashion, false
+    // otherwise.
+    bool WaitForConnection(std::chrono::milliseconds timeout);
+
+    // Can be called from any thread when the connection stops being pending.
+    // Only the first invocation will be acknowledged, the rest will be no-ops.
+    void SetConnectionEstablished(bool success);
+
+  private:
+    bool connection_established_ GUARDED_BY(mutex_) = false;
+    bool connection_established_ready_ GUARDED_BY(mutex_) = false;
+    std::mutex mutex_;
+    std::condition_variable cv_;
+
+    DISALLOW_COPY_AND_ASSIGN(ConnectionWaitable);
+};
+
 class atransport {
   public:
     // TODO(danalbert): We expose waaaaaaay too much stuff because this was
@@ -168,13 +199,16 @@
     // it's better to do this piece by piece.
 
     atransport(ConnectionState state = kCsOffline)
-        : id(NextTransportId()), connection_state_(state) {
+        : id(NextTransportId()),
+          connection_state_(state),
+          connection_waitable_(std::make_shared<ConnectionWaitable>()),
+          connection_(nullptr) {
         // Initialize protocol to min version for compatibility with older versions.
         // Version will be updated post-connect.
         protocol_version = A_VERSION_MIN;
         max_payload = MAX_PAYLOAD;
     }
-    virtual ~atransport() {}
+    virtual ~atransport();
 
     int Write(apacket* p);
     void Kick();
@@ -183,13 +217,17 @@
     ConnectionState GetConnectionState() const;
     void SetConnectionState(ConnectionState state);
 
+    void SetConnection(std::unique_ptr<Connection> connection);
+    std::shared_ptr<Connection> connection() {
+        std::lock_guard<std::mutex> lock(mutex_);
+        return connection_;
+    }
+
     const TransportId id;
     size_t ref_count = 0;
     bool online = false;
     TransportType type = kTransportAny;
 
-    std::unique_ptr<Connection> connection;
-
     // Used to identify transports for clients.
     char* serial = nullptr;
     char* product = nullptr;
@@ -241,7 +279,14 @@
     // This is to make it easier to use the same network target for both fastboot and adb.
     bool MatchesTarget(const std::string& target) const;
 
-private:
+    // Notifies that the atransport is no longer waiting for the connection
+    // being established.
+    void SetConnectionEstablished(bool success);
+
+    // Gets a shared reference to the ConnectionWaitable.
+    std::shared_ptr<ConnectionWaitable> connection_waitable() { return connection_waitable_; }
+
+  private:
     bool kicked_ = false;
 
     // A set of features transmitted in the banner with the initial connection.
@@ -258,6 +303,15 @@
     std::deque<std::shared_ptr<RSA>> keys_;
 #endif
 
+    // A sharable object that can be used to wait for the atransport's
+    // connection to be established.
+    std::shared_ptr<ConnectionWaitable> connection_waitable_;
+
+    // The underlying connection object.
+    std::shared_ptr<Connection> connection_ GUARDED_BY(mutex_);
+
+    std::mutex mutex_;
+
     DISALLOW_COPY_AND_ASSIGN(atransport);
 };
 
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index c09fcb7..e81f27c 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -101,7 +101,11 @@
     int ret = register_socket_transport(fd, serial.c_str(), port, 0);
     if (ret < 0) {
         adb_close(fd);
-        *response = android::base::StringPrintf("already connected to %s", serial.c_str());
+        if (ret == -EALREADY) {
+            *response = android::base::StringPrintf("already connected to %s", serial.c_str());
+        } else {
+            *response = android::base::StringPrintf("failed to connect to %s", serial.c_str());
+        }
     } else {
         *response = android::base::StringPrintf("connected to %s", serial.c_str());
     }
@@ -452,7 +456,8 @@
     // Emulator connection.
     if (local) {
         auto emulator_connection = std::make_unique<EmulatorConnection>(std::move(fd), adb_port);
-        t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(emulator_connection));
+        t->SetConnection(
+            std::make_unique<BlockingConnectionAdapter>(std::move(emulator_connection)));
         std::lock_guard<std::mutex> lock(local_transports_lock);
         atransport* existing_transport = find_emulator_transport_by_adb_port_locked(adb_port);
         if (existing_transport != NULL) {
@@ -472,6 +477,6 @@
 
     // Regular tcp connection.
     auto fd_connection = std::make_unique<FdConnection>(std::move(fd));
-    t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(fd_connection));
+    t->SetConnection(std::make_unique<BlockingConnectionAdapter>(std::move(fd_connection)));
     return fail;
 }
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index e9a75cd..94b2e37 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -176,7 +176,7 @@
 void init_usb_transport(atransport* t, usb_handle* h) {
     D("transport: usb");
     auto connection = std::make_unique<UsbConnection>(h);
-    t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(connection));
+    t->SetConnection(std::make_unique<BlockingConnectionAdapter>(std::move(connection)));
     t->type = kTransportUsb;
 }
 
diff --git a/base/Android.bp b/base/Android.bp
index 12b3969..ec81f61 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -162,4 +162,5 @@
             suffix: "64",
         },
     },
+    test_suites: ["device-tests"],
 }
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index 2c8570e..1b7cc5f 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <limits>
 #include <string>
@@ -31,14 +32,20 @@
 // otherwise valid values will be rejected. Returns boolean success; 'out'
 // is untouched if parsing fails.
 template <typename T>
-bool ParseUint(const char* s, T* out,
-               T max = std::numeric_limits<T>::max()) {
+bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
+               bool allow_suffixes = false) {
   int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
   errno = 0;
   char* end;
   unsigned long long int result = strtoull(s, &end, base);
-  if (errno != 0 || s == end || *end != '\0') {
-    return false;
+  if (errno != 0 || end == s) return false;
+  if (*end != '\0') {
+    const char* suffixes = "bkmgtpe";
+    const char* suffix;
+    if (!allow_suffixes || (suffix = strchr(suffixes, tolower(*end))) == nullptr) return false;
+#if __clang__  // TODO: win32 still builds with GCC :-(
+    if (__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) return false;
+#endif
   }
   if (max < result) {
     return false;
@@ -49,9 +56,20 @@
 
 // TODO: string_view
 template <typename T>
-bool ParseUint(const std::string& s, T* out,
-               T max = std::numeric_limits<T>::max()) {
-  return ParseUint(s.c_str(), out, max);
+bool ParseUint(const std::string& s, T* out, T max = std::numeric_limits<T>::max(),
+               bool allow_suffixes = false) {
+  return ParseUint(s.c_str(), out, max, allow_suffixes);
+}
+
+template <typename T>
+bool ParseByteCount(const char* s, T* out, T max = std::numeric_limits<T>::max()) {
+  return ParseUint(s, out, max, true);
+}
+
+// TODO: string_view
+template <typename T>
+bool ParseByteCount(const std::string& s, T* out, T max = std::numeric_limits<T>::max()) {
+  return ParseByteCount(s.c_str(), out, max);
 }
 
 // Parses the signed decimal integer in the string 's' and sets 'out' to
diff --git a/base/parseint_test.cpp b/base/parseint_test.cpp
index 483b1d3..fb1c339 100644
--- a/base/parseint_test.cpp
+++ b/base/parseint_test.cpp
@@ -96,3 +96,44 @@
   ASSERT_FALSE(android::base::ParseInt("456x", &u));
   ASSERT_EQ(123u, u);
 }
+
+TEST(parseint, ParseByteCount) {
+  uint64_t i = 0;
+  ASSERT_TRUE(android::base::ParseByteCount("123b", &i));
+  ASSERT_EQ(123ULL, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("8k", &i));
+  ASSERT_EQ(8ULL * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("8M", &i));
+  ASSERT_EQ(8ULL * 1024 * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("6g", &i));
+  ASSERT_EQ(6ULL * 1024 * 1024 * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("1T", &i));
+  ASSERT_EQ(1ULL * 1024 * 1024 * 1024 * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("2p", &i));
+  ASSERT_EQ(2ULL * 1024 * 1024 * 1024 * 1024 * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("4e", &i));
+  ASSERT_EQ(4ULL * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, i);
+}
+
+TEST(parseint, ParseByteCount_invalid_suffix) {
+  unsigned u;
+  ASSERT_FALSE(android::base::ParseByteCount("1x", &u));
+}
+
+TEST(parseint, ParseByteCount_overflow) {
+  uint64_t u64;
+  ASSERT_FALSE(android::base::ParseByteCount("4294967295E", &u64));
+
+  uint16_t u16;
+  ASSERT_TRUE(android::base::ParseByteCount("63k", &u16));
+  ASSERT_EQ(63U * 1024, u16);
+  ASSERT_TRUE(android::base::ParseByteCount("65535b", &u16));
+  ASSERT_EQ(65535U, u16);
+  ASSERT_FALSE(android::base::ParseByteCount("65k", &u16));
+}
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index b194bbe..01b8948 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -312,6 +312,7 @@
 init    : processing action (ro.boot.bootreason=*) from (/system/etc/init/bootstat.rc
 init    : processing action (sys.boot_completed=1 && sys.logbootcomplete=1) from (/system/etc/init/bootstat.rc
  (/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
+ (/system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
  (/system/bin/bootstat -r post_decrypt_time_elapsed)'
 init    : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
 init    : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
@@ -582,9 +583,9 @@
   duration_test
   case ${TEST} in
     bootloader | recovery | cold | hard | warm ) reason=${TEST} ;;
-    *)                                           reason=reboot,${TEST} ;;
+    *)                                           reason=reboot,${TEST#optional_} ;;
   esac
-  adb reboot ${TEST}
+  adb reboot ${TEST#optional_}
   wait_for_screen
   bootloader_reason=`validate_property ro.boot.bootreason`
   EXPECT_PROPERTY ro.boot.bootreason ${bootloader_reason}
@@ -948,6 +949,20 @@
   report_bootstat_logs reboot,adb
 }
 
+[ "USAGE: test_rescueparty
+
+rescueparty test
+- adb reboot rescueparty
+- (wait until screen is up, boot has completed)
+- adb shell getprop sys.boot.reason
+- adb shell getprop ro.boot.bootreason
+- NB: should report reboot,rescueparty" ]
+test_optional_rescueparty() {
+  blind_reboot_test
+  echo "WARNING: legacy devices are allowed to fail following ro.boot.bootreason result" >&2
+  EXPECT_PROPERTY ro.boot.bootreason reboot,rescueparty
+}
+
 [ "USAGE: test_Its_Just_So_Hard_reboot
 
 Its Just So Hard reboot test:
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index c2688e9..1b13b21 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -232,7 +232,7 @@
     {"shutdown,thermal,battery", 87},
     {"reboot,its_just_so_hard", 88},  // produced by boot_reason_test
     {"reboot,Its Just So Hard", 89},  // produced by boot_reason_test
-    // {"usb", 90},  // Duplicate of enum 80 above. Immediate reuse possible.
+    {"reboot,rescueparty", 90},
     {"charge", 91},
     {"oem_tz_crash", 92},
     {"uvlo", 93},
@@ -303,6 +303,9 @@
     {"kernel_panic,init", 158},
     {"kernel_panic,oom", 159},
     {"kernel_panic,stack", 160},
+    {"kernel_panic,sysrq,livelock,alarm", 161},   // llkd
+    {"kernel_panic,sysrq,livelock,driver", 162},  // llkd
+    {"kernel_panic,sysrq,livelock,zombie", 163},  // llkd
 };
 
 // Converts a string value representing the reason the system booted to an
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 7e6f24d..7c28b28 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -112,7 +112,6 @@
         "libbase",
         "libdebuggerd",
         "libbacktrace",
-        "libunwind",
         "libunwindstack",
         "libdexfile",
         "liblzma",
@@ -158,7 +157,6 @@
 
     static_libs: [
         "libbacktrace",
-        "libunwind",
         "libunwindstack",
         "liblzma",
         "libbase",
@@ -221,6 +219,8 @@
             stem: "debuggerd_test64",
         },
     },
+
+    test_suites: ["device-tests"],
 }
 
 cc_benchmark {
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index a1f0211..40cf6c3 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -190,6 +190,19 @@
 static unique_fd g_tombstoned_socket;
 static unique_fd g_output_fd;
 
+static void DefuseSignalHandlers() {
+  // Don't try to dump ourselves.
+  struct sigaction action = {};
+  action.sa_handler = SIG_DFL;
+  debuggerd_register_handlers(&action);
+
+  sigset_t mask;
+  sigemptyset(&mask);
+  if (sigprocmask(SIG_SETMASK, &mask, nullptr) != 0) {
+    PLOG(FATAL) << "failed to set signal mask";
+  }
+}
+
 static void Initialize(char** argv) {
   android::base::InitLogging(argv);
   android::base::SetAborter([](const char* abort_msg) {
@@ -213,17 +226,6 @@
 
     _exit(1);
   });
-
-  // Don't try to dump ourselves.
-  struct sigaction action = {};
-  action.sa_handler = SIG_DFL;
-  debuggerd_register_handlers(&action);
-
-  sigset_t mask;
-  sigemptyset(&mask);
-  if (sigprocmask(SIG_SETMASK, &mask, nullptr) != 0) {
-    PLOG(FATAL) << "failed to set signal mask";
-  }
 }
 
 static void ParseArgs(int argc, char** argv, pid_t* pseudothread_tid, DebuggerdDumpType* dump_type) {
@@ -321,6 +323,8 @@
 }
 
 int main(int argc, char** argv) {
+  DefuseSignalHandlers();
+
   atrace_begin(ATRACE_TAG, "before reparent");
   pid_t target_process = getppid();
 
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index e410be9..9b64be7 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -346,7 +346,9 @@
 
   std::string result;
   ConsumeFd(std::move(output_fd), &result);
-  ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER\), fault addr --------)");
+  ASSERT_MATCH(
+      result,
+      R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER from pid \d+, uid \d+\), fault addr --------)");
   ASSERT_MATCH(result, R"(backtrace:)");
 }
 
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 05e6efa..c07a34a 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -169,24 +169,26 @@
     return;
   }
 
-  const char* signal_name = get_signame(info->si_signo);
-  bool has_address = signal_has_si_addr(info->si_signo, info->si_code);
-
-  // Many signals don't have an address.
+  // Many signals don't have an address or sender.
   char addr_desc[32] = "";  // ", fault addr 0x1234"
-  if (has_address) {
+  if (signal_has_si_addr(info)) {
     async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
   }
+  pid_t self_pid = __getpid();
+  char sender_desc[32] = {};  // " from pid 1234, uid 666"
+  if (signal_has_sender(info, self_pid)) {
+    get_signal_sender(sender_desc, sizeof(sender_desc), info);
+  }
 
   char main_thread_name[MAX_TASK_NAME_LEN + 1];
   if (!get_main_thread_name(main_thread_name, sizeof(main_thread_name))) {
     strncpy(main_thread_name, "<unknown>", sizeof(main_thread_name));
   }
 
-  async_safe_format_log(
-      ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s), code %d (%s)%s in tid %d (%s), pid %d (%s)",
-      info->si_signo, signal_name, info->si_code, get_sigcode(info->si_signo, info->si_code),
-      addr_desc, __gettid(), thread_name, __getpid(), main_thread_name);
+  async_safe_format_log(ANDROID_LOG_FATAL, "libc",
+                        "Fatal signal %d (%s), code %d (%s%s)%s in tid %d (%s), pid %d (%s)",
+                        info->si_signo, get_signame(info), info->si_code, get_sigcode(info),
+                        sender_desc, addr_desc, __gettid(), thread_name, self_pid, main_thread_name);
 }
 
 /*
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 7b04e71..7c5304e 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -74,8 +74,10 @@
 
 void drop_capabilities();
 
-bool signal_has_si_addr(int si_signo, int si_code);
-const char* get_signame(int sig);
-const char* get_sigcode(int signo, int code);
+bool signal_has_sender(const siginfo_t*, pid_t caller_pid);
+bool signal_has_si_addr(const siginfo_t*);
+void get_signal_sender(char* buf, size_t n, const siginfo_t*);
+const char* get_signame(const siginfo_t*);
+const char* get_sigcode(const siginfo_t*);
 
 #endif // _DEBUGGERD_UTILITY_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 55d6204..e11be1e 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -102,18 +102,24 @@
   if (!cause.empty()) _LOG(log, logtype::HEADER, "Cause: %s\n", cause.c_str());
 }
 
-static void dump_signal_info(log_t* log, const siginfo_t* si) {
+static void dump_signal_info(log_t* log, const ThreadInfo& thread_info) {
   char addr_desc[32]; // ", fault addr 0x1234"
-  if (signal_has_si_addr(si->si_signo, si->si_code)) {
-    snprintf(addr_desc, sizeof(addr_desc), "%p", si->si_addr);
+  if (signal_has_si_addr(thread_info.siginfo)) {
+    snprintf(addr_desc, sizeof(addr_desc), "%p", thread_info.siginfo->si_addr);
   } else {
     snprintf(addr_desc, sizeof(addr_desc), "--------");
   }
 
-  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n", si->si_signo,
-       get_signame(si->si_signo), si->si_code, get_sigcode(si->si_signo, si->si_code), addr_desc);
+  char sender_desc[32] = {};  // " from pid 1234, uid 666"
+  if (signal_has_sender(thread_info.siginfo, thread_info.pid)) {
+    get_signal_sender(sender_desc, sizeof(sender_desc), thread_info.siginfo);
+  }
 
-  dump_probable_cause(log, si);
+  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s%s), fault addr %s\n",
+       thread_info.siginfo->si_signo, get_signame(thread_info.siginfo),
+       thread_info.siginfo->si_code, get_sigcode(thread_info.siginfo), sender_desc, addr_desc);
+
+  dump_probable_cause(log, thread_info.siginfo);
 }
 
 static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) {
@@ -247,14 +253,13 @@
 
   length -= sizeof(size_t);
 
-  std::vector<char> msg(length);
+  // The abort message should be null terminated already, but reserve a spot for NUL just in case.
+  std::vector<char> msg(length + 1);
   if (!process_memory->ReadFully(address + sizeof(length), &msg[0], length)) {
     _LOG(log, logtype::HEADER, "Failed to read abort message: %s\n", strerror(errno));
     return;
   }
 
-  // The abort message should be null terminated already, but just in case...
-  msg[length] = '\0';
   _LOG(log, logtype::HEADER, "Abort message: '%s'\n", &msg[0]);
 }
 
@@ -413,7 +418,7 @@
   dump_thread_info(log, thread_info);
 
   if (thread_info.siginfo) {
-    dump_signal_info(log, thread_info.siginfo);
+    dump_signal_info(log, thread_info);
   }
 
   if (primary_thread) {
@@ -422,8 +427,10 @@
 
   dump_registers(log, thread_info.registers.get());
 
+  // Unwind will mutate the registers, so make a copy first.
+  std::unique_ptr<Regs> regs_copy(thread_info.registers->Clone());
   std::vector<backtrace_frame_data_t> frames;
-  if (!Backtrace::Unwind(thread_info.registers.get(), map, &frames, 0, nullptr)) {
+  if (!Backtrace::Unwind(regs_copy.get(), map, &frames, 0, nullptr)) {
     _LOG(log, logtype::THREAD, "Failed to unwind");
     return false;
   }
@@ -441,7 +448,7 @@
     if (map) {
       uint64_t addr = 0;
       siginfo_t* si = thread_info.siginfo;
-      if (signal_has_si_addr(si->si_signo, si->si_code)) {
+      if (signal_has_si_addr(si)) {
         addr = reinterpret_cast<uint64_t>(si->si_addr);
       }
       dump_all_maps(log, map, process_memory, addr);
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 1ad1800..1f6f3c8 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -254,13 +254,13 @@
   }
 }
 
-bool signal_has_si_addr(int si_signo, int si_code) {
+bool signal_has_si_addr(const siginfo_t* si) {
   // Manually sent signals won't have si_addr.
-  if (si_code == SI_USER || si_code == SI_QUEUE || si_code == SI_TKILL) {
+  if (si->si_code == SI_USER || si->si_code == SI_QUEUE || si->si_code == SI_TKILL) {
     return false;
   }
 
-  switch (si_signo) {
+  switch (si->si_signo) {
     case SIGBUS:
     case SIGFPE:
     case SIGILL:
@@ -272,8 +272,16 @@
   }
 }
 
-const char* get_signame(int sig) {
-  switch (sig) {
+bool signal_has_sender(const siginfo_t* si, pid_t caller_pid) {
+  return SI_FROMUSER(si) && (si->si_pid != 0) && (si->si_pid != caller_pid);
+}
+
+void get_signal_sender(char* buf, size_t n, const siginfo_t* si) {
+  snprintf(buf, n, " from pid %d, uid %d", si->si_pid, si->si_uid);
+}
+
+const char* get_signame(const siginfo_t* si) {
+  switch (si->si_signo) {
     case SIGABRT: return "SIGABRT";
     case SIGBUS: return "SIGBUS";
     case SIGFPE: return "SIGFPE";
@@ -290,11 +298,11 @@
   }
 }
 
-const char* get_sigcode(int signo, int code) {
+const char* get_sigcode(const siginfo_t* si) {
   // Try the signal-specific codes...
-  switch (signo) {
+  switch (si->si_signo) {
     case SIGILL:
-      switch (code) {
+      switch (si->si_code) {
         case ILL_ILLOPC: return "ILL_ILLOPC";
         case ILL_ILLOPN: return "ILL_ILLOPN";
         case ILL_ILLADR: return "ILL_ILLADR";
@@ -307,7 +315,7 @@
       static_assert(NSIGILL == ILL_BADSTK, "missing ILL_* si_code");
       break;
     case SIGBUS:
-      switch (code) {
+      switch (si->si_code) {
         case BUS_ADRALN: return "BUS_ADRALN";
         case BUS_ADRERR: return "BUS_ADRERR";
         case BUS_OBJERR: return "BUS_OBJERR";
@@ -317,7 +325,7 @@
       static_assert(NSIGBUS == BUS_MCEERR_AO, "missing BUS_* si_code");
       break;
     case SIGFPE:
-      switch (code) {
+      switch (si->si_code) {
         case FPE_INTDIV: return "FPE_INTDIV";
         case FPE_INTOVF: return "FPE_INTOVF";
         case FPE_FLTDIV: return "FPE_FLTDIV";
@@ -330,7 +338,7 @@
       static_assert(NSIGFPE == FPE_FLTSUB, "missing FPE_* si_code");
       break;
     case SIGSEGV:
-      switch (code) {
+      switch (si->si_code) {
         case SEGV_MAPERR: return "SEGV_MAPERR";
         case SEGV_ACCERR: return "SEGV_ACCERR";
 #if defined(SEGV_BNDERR)
@@ -350,21 +358,21 @@
       break;
 #if defined(SYS_SECCOMP) // Our glibc is too old, and we build this for the host too.
     case SIGSYS:
-      switch (code) {
+      switch (si->si_code) {
         case SYS_SECCOMP: return "SYS_SECCOMP";
       }
       static_assert(NSIGSYS == SYS_SECCOMP, "missing SYS_* si_code");
       break;
 #endif
     case SIGTRAP:
-      switch (code) {
+      switch (si->si_code) {
         case TRAP_BRKPT: return "TRAP_BRKPT";
         case TRAP_TRACE: return "TRAP_TRACE";
         case TRAP_BRANCH: return "TRAP_BRANCH";
         case TRAP_HWBKPT: return "TRAP_HWBKPT";
       }
-      if ((code & 0xff) == SIGTRAP) {
-        switch ((code >> 8) & 0xff) {
+      if ((si->si_code & 0xff) == SIGTRAP) {
+        switch ((si->si_code >> 8) & 0xff) {
           case PTRACE_EVENT_FORK:
             return "PTRACE_EVENT_FORK";
           case PTRACE_EVENT_VFORK:
@@ -387,7 +395,7 @@
       break;
   }
   // Then the other codes...
-  switch (code) {
+  switch (si->si_code) {
     case SI_USER: return "SI_USER";
     case SI_KERNEL: return "SI_KERNEL";
     case SI_QUEUE: return "SI_QUEUE";
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 1bf8f14..15ae406 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -61,10 +61,11 @@
 struct Crash {
   ~Crash() { event_free(crash_event); }
 
-  unique_fd crash_fd;
+  std::string crash_tombstone_path;
+  unique_fd crash_tombstone_fd;
+  unique_fd crash_socket_fd;
   pid_t crash_pid;
   event* crash_event = nullptr;
-  std::string crash_path;
 
   DebuggerdDumpType crash_type;
 };
@@ -109,24 +110,29 @@
     return &queue;
   }
 
-  std::pair<unique_fd, std::string> get_output() {
-    unique_fd result;
-    std::string file_name = StringPrintf("%s%02d", file_name_prefix_.c_str(), next_artifact_);
-
-    // Unlink and create the file, instead of using O_TRUNC, to avoid two processes
-    // interleaving their output in case we ever get into that situation.
-    if (unlinkat(dir_fd_, file_name.c_str(), 0) != 0 && errno != ENOENT) {
-      PLOG(FATAL) << "failed to unlink tombstone at " << dir_path_ << "/" << file_name;
-    }
-
-    result.reset(openat(dir_fd_, file_name.c_str(),
-                        O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
+  std::pair<std::string, unique_fd> get_output() {
+    std::string path;
+    unique_fd result(openat(dir_fd_, ".", O_WRONLY | O_APPEND | O_TMPFILE | O_CLOEXEC, 0640));
     if (result == -1) {
-      PLOG(FATAL) << "failed to create tombstone at " << dir_path_ << "/" << file_name;
-    }
+      // We might not have O_TMPFILE. Try creating with an arbitrary filename instead.
+      static size_t counter = 0;
+      std::string tmp_filename = StringPrintf(".temporary%zu", counter++);
+      result.reset(openat(dir_fd_, tmp_filename.c_str(),
+                          O_WRONLY | O_APPEND | O_CREAT | O_TRUNC | O_CLOEXEC, 0640));
+      if (result == -1) {
+        PLOG(FATAL) << "failed to create temporary tombstone in " << dir_path_;
+      }
 
+      path = StringPrintf("%s/%s", dir_path_.c_str(), tmp_filename.c_str());
+    }
+    return std::make_pair(std::move(path), std::move(result));
+  }
+
+  std::string get_next_artifact_path() {
+    std::string file_name =
+        StringPrintf("%s/%s%02d", dir_path_.c_str(), file_name_prefix_.c_str(), next_artifact_);
     next_artifact_ = (next_artifact_ + 1) % max_artifacts_;
-    return {std::move(result), dir_path_ + "/" + file_name};
+    return file_name;
   }
 
   bool maybe_enqueue_crash(Crash* crash) {
@@ -203,14 +209,17 @@
 
 static void perform_request(Crash* crash) {
   unique_fd output_fd;
-  if (!intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd)) {
-    std::tie(output_fd, crash->crash_path) = CrashQueue::for_crash(crash)->get_output();
+  bool intercepted =
+      intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd);
+  if (!intercepted) {
+    std::tie(crash->crash_tombstone_path, output_fd) = CrashQueue::for_crash(crash)->get_output();
+    crash->crash_tombstone_fd.reset(dup(output_fd.get()));
   }
 
   TombstonedCrashPacket response = {
     .packet_type = CrashPacketType::kPerformDump
   };
-  ssize_t rc = send_fd(crash->crash_fd, &response, sizeof(response), std::move(output_fd));
+  ssize_t rc = send_fd(crash->crash_socket_fd, &response, sizeof(response), std::move(output_fd));
   if (rc == -1) {
     PLOG(WARNING) << "failed to send response to CrashRequest";
     goto fail;
@@ -222,7 +231,7 @@
     struct timeval timeout = { 10, 0 };
 
     event_base* base = event_get_base(crash->crash_event);
-    event_assign(crash->crash_event, base, crash->crash_fd, EV_TIMEOUT | EV_READ,
+    event_assign(crash->crash_event, base, crash->crash_socket_fd, EV_TIMEOUT | EV_READ,
                  crash_completed_cb, crash);
     event_add(crash->crash_event, &timeout);
   }
@@ -243,7 +252,7 @@
   // and only native crashes on the native socket.
   struct timeval timeout = { 1, 0 };
   event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
-  crash->crash_fd.reset(sockfd);
+  crash->crash_socket_fd.reset(sockfd);
   crash->crash_event = crash_event;
   event_add(crash_event, &timeout);
 }
@@ -342,14 +351,37 @@
     goto fail;
   }
 
-  if (!crash->crash_path.empty()) {
-    if (crash->crash_type == kDebuggerdJavaBacktrace) {
-      LOG(ERROR) << "Traces for pid " << crash->crash_pid << " written to: " << crash->crash_path;
+  if (crash->crash_tombstone_fd != -1) {
+    std::string fd_path = StringPrintf("/proc/self/fd/%d", crash->crash_tombstone_fd.get());
+    std::string tombstone_path = CrashQueue::for_crash(crash)->get_next_artifact_path();
+
+    // linkat doesn't let us replace a file, so we need to unlink first.
+    int rc = unlink(tombstone_path.c_str());
+    if (rc != 0 && errno != ENOENT) {
+      PLOG(ERROR) << "failed to unlink tombstone at " << tombstone_path;
+      goto fail;
+    }
+
+    rc = linkat(AT_FDCWD, fd_path.c_str(), AT_FDCWD, tombstone_path.c_str(), AT_SYMLINK_FOLLOW);
+    if (rc != 0) {
+      PLOG(ERROR) << "failed to link tombstone";
     } else {
-      // NOTE: Several tools parse this log message to figure out where the
-      // tombstone associated with a given native crash was written. Any changes
-      // to this message must be carefully considered.
-      LOG(ERROR) << "Tombstone written to: " << crash->crash_path;
+      if (crash->crash_type == kDebuggerdJavaBacktrace) {
+        LOG(ERROR) << "Traces for pid " << crash->crash_pid << " written to: " << tombstone_path;
+      } else {
+        // NOTE: Several tools parse this log message to figure out where the
+        // tombstone associated with a given native crash was written. Any changes
+        // to this message must be carefully considered.
+        LOG(ERROR) << "Tombstone written to: " << tombstone_path;
+      }
+    }
+
+    // If we don't have O_TMPFILE, we need to clean up after ourselves.
+    if (!crash->crash_tombstone_path.empty()) {
+      rc = unlink(crash->crash_tombstone_path.c_str());
+      if (rc != 0) {
+        PLOG(ERROR) << "failed to unlink temporary tombstone at " << crash->crash_tombstone_path;
+      }
     }
   }
 
diff --git a/demangle/Android.bp b/demangle/Android.bp
index 8d5b135..cf6abfd 100644
--- a/demangle/Android.bp
+++ b/demangle/Android.bp
@@ -78,4 +78,9 @@
     shared_libs: [
         "libdemangle",
     ],
+
+    test_suites: ["device-tests"],
+    required: [
+        "libdemangle",
+    ],
 }
diff --git a/demangle/Android.mk b/demangle/Android.mk
index e3cfc2a..d8082a9 100644
--- a/demangle/Android.mk
+++ b/demangle/Android.mk
@@ -19,7 +19,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := demangle_fuzzer
-LOCAL_MODULE_TAGS := optional
 LOCAL_SRC_FILES := \
     Demangler.cpp \
     demangle_fuzzer.cpp \
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 9bd0628..983e195 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -101,14 +101,13 @@
 #
 
 my_dist_files := $(HOST_OUT_EXECUTABLES)/fastboot
-my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
-my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid$(HOST_EXECUTABLE_SUFFIX)
-my_dist_files += $(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX)
-my_dist_files += $(HOST_OUT_EXECUTABLES)/sload_f2fs$(HOST_EXECUTABLE_SUFFIX)
+my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs
+my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid
+my_dist_files += $(HOST_OUT_EXECUTABLES)/make_f2fs
+my_dist_files += $(HOST_OUT_EXECUTABLES)/sload_f2fs
 $(call dist-for-goals,dist_files sdk win_sdk,$(my_dist_files))
 ifdef HOST_CROSS_OS
-# Archive fastboot.exe for win_sdk build.
-$(call dist-for-goals,win_sdk,$(ALL_MODULES.host_cross_fastboot.BUILT))
+$(call dist-for-goals,dist_files sdk win_sdk,$(ALL_MODULES.host_cross_fastboot.BUILT))
 endif
 my_dist_files :=
 
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 41a3d6b..9463cc9 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -82,7 +82,7 @@
 // libsparse will support INT_MAX, but this results in large allocations, so
 // let's keep it at 1GB to avoid memory pressure on the host.
 static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024;
-static int64_t sparse_limit = -1;
+static uint64_t sparse_limit = 0;
 static int64_t target_sparse_limit = -1;
 
 static unsigned g_base_addr = 0x10000000;
@@ -375,7 +375,7 @@
             " -w                         Wipe userdata.\n"
             " -s SERIAL                  Specify a USB device.\n"
             " -s tcp|udp:HOST[:PORT]     Specify a network device.\n"
-            " -S SIZE[K|M|G]             Use sparse files above this limit (0 to disable).\n"
+            " -S SIZE[K|M|G]             Break into sparse files no larger than SIZE.\n"
             " --slot SLOT                Use SLOT; 'all' for both slots, 'other' for\n"
             "                            non-current slot (default: current active slot).\n"
             " --set-active[=SLOT]        Sets the active slot before rebooting.\n"
@@ -693,10 +693,14 @@
     fb_queue_notice("--------------------------------------------");
 }
 
-static struct sparse_file** load_sparse_files(int fd, int max_size) {
+static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
     struct sparse_file* s = sparse_file_import_auto(fd, false, true);
     if (!s) die("cannot sparse read file");
 
+    if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) {
+      die("invalid max size %" PRId64, max_size);
+    }
+
     int files = sparse_file_resparse(s, max_size, nullptr, 0);
     if (files < 0) die("Failed to resparse");
 
@@ -730,13 +734,10 @@
 }
 
 static int64_t get_sparse_limit(Transport* transport, int64_t size) {
-    int64_t limit;
-
-    if (sparse_limit == 0) {
-        return 0;
-    } else if (sparse_limit > 0) {
-        limit = sparse_limit;
-    } else {
+    int64_t limit = sparse_limit;
+    if (limit == 0) {
+        // Unlimited, so see what the target device's limit is.
+        // TODO: shouldn't we apply this limit even if you've used -S?
         if (target_sparse_limit == -1) {
             target_sparse_limit = get_target_sparse_limit(transport);
         }
@@ -1197,47 +1198,6 @@
     fb_queue_command(command, "");
 }
 
-static int64_t parse_num(const char *arg)
-{
-    char *endptr;
-    unsigned long long num;
-
-    num = strtoull(arg, &endptr, 0);
-    if (endptr == arg) {
-        return -1;
-    }
-
-    if (*endptr == 'k' || *endptr == 'K') {
-        if (num >= (-1ULL) / 1024) {
-            return -1;
-        }
-        num *= 1024LL;
-        endptr++;
-    } else if (*endptr == 'm' || *endptr == 'M') {
-        if (num >= (-1ULL) / (1024 * 1024)) {
-            return -1;
-        }
-        num *= 1024LL * 1024LL;
-        endptr++;
-    } else if (*endptr == 'g' || *endptr == 'G') {
-        if (num >= (-1ULL) / (1024 * 1024 * 1024)) {
-            return -1;
-        }
-        num *= 1024LL * 1024LL * 1024LL;
-        endptr++;
-    }
-
-    if (*endptr != '\0') {
-        return -1;
-    }
-
-    if (num > INT64_MAX) {
-        return -1;
-    }
-
-    return num;
-}
-
 static std::string fb_fix_numeric_var(std::string var) {
     // Some bootloaders (angler, for example), send spurious leading whitespace.
     var = android::base::Trim(var);
@@ -1471,8 +1431,9 @@
                     serial = optarg;
                     break;
                 case 'S':
-                    sparse_limit = parse_num(optarg);
-                    if (sparse_limit < 0) die("invalid sparse limit");
+                    if (!android::base::ParseByteCount(optarg, &sparse_limit)) {
+                        die("invalid sparse limit %s", optarg);
+                    }
                     break;
                 case 'v':
                     set_verbose();
@@ -1683,20 +1644,20 @@
     }
 
     if (wants_wipe) {
-        fb_queue_erase("userdata");
-        if (set_fbe_marker) {
-            fprintf(stderr, "setting FBE marker on initial userdata...\n");
-            std::string initial_userdata_dir = create_fbemarker_tmpdir();
-            fb_perform_format(transport, "userdata", 1, "", "", initial_userdata_dir);
-            delete_fbemarker_tmpdir(initial_userdata_dir);
-        } else {
-            fb_perform_format(transport, "userdata", 1, "", "", "");
-        }
-
-        std::string cache_type;
-        if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
-            fb_queue_erase("cache");
-            fb_perform_format(transport, "cache", 1, "", "", "");
+        std::vector<std::string> partitions = { "userdata", "cache", "metadata" };
+        for (const auto& partition : partitions) {
+            std::string partition_type;
+            if (!fb_getvar(transport, std::string{"partition-type:"} + partition, &partition_type)) continue;
+            if (partition_type.empty()) continue;
+            fb_queue_erase(partition);
+            if (partition == "userdata" && set_fbe_marker) {
+                fprintf(stderr, "setting FBE marker on initial userdata...\n");
+                std::string initial_userdata_dir = create_fbemarker_tmpdir();
+                fb_perform_format(transport, partition, 1, "", "", initial_userdata_dir);
+                delete_fbemarker_tmpdir(initial_userdata_dir);
+            } else {
+                fb_perform_format(transport, partition, 1, "", "", "");
+            }
         }
     }
     if (wants_set_active) {
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index a089567..fda6f5d 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -278,19 +278,14 @@
     return _command_end(transport);
 }
 
-#define TRANSPORT_BUF_SIZE 1024
+static constexpr size_t TRANSPORT_BUF_SIZE = 1024;
 static char transport_buf[TRANSPORT_BUF_SIZE];
-static int transport_buf_len;
+static size_t transport_buf_len;
 
-static int fb_download_data_sparse_write(void *priv, const void *data, int len)
-{
-    int r;
-    Transport* transport = reinterpret_cast<Transport*>(priv);
-    int to_write;
-    const char* ptr = reinterpret_cast<const char*>(data);
-
+static int fb_download_data_sparse_write(void* priv, const void* data, size_t len) {
+    const char* ptr = static_cast<const char*>(data);
     if (transport_buf_len) {
-        to_write = std::min(TRANSPORT_BUF_SIZE - transport_buf_len, len);
+        size_t to_write = std::min(TRANSPORT_BUF_SIZE - transport_buf_len, len);
 
         memcpy(transport_buf + transport_buf_len, ptr, to_write);
         transport_buf_len += to_write;
@@ -298,9 +293,10 @@
         len -= to_write;
     }
 
+    Transport* transport = static_cast<Transport*>(priv);
     if (transport_buf_len == TRANSPORT_BUF_SIZE) {
-        r = _command_write_data(transport, transport_buf, TRANSPORT_BUF_SIZE);
-        if (r != TRANSPORT_BUF_SIZE) {
+        int64_t r = _command_write_data(transport, transport_buf, TRANSPORT_BUF_SIZE);
+        if (r != static_cast<int64_t>(TRANSPORT_BUF_SIZE)) {
             return -1;
         }
         transport_buf_len = 0;
@@ -311,9 +307,9 @@
             g_error = "internal error: transport_buf not empty";
             return -1;
         }
-        to_write = round_down(len, TRANSPORT_BUF_SIZE);
-        r = _command_write_data(transport, ptr, to_write);
-        if (r != to_write) {
+        size_t to_write = round_down(len, TRANSPORT_BUF_SIZE);
+        int64_t r = _command_write_data(transport, ptr, to_write);
+        if (r != static_cast<int64_t>(to_write)) {
             return -1;
         }
         ptr += to_write;
@@ -344,12 +340,12 @@
 }
 
 int fb_download_data_sparse(Transport* transport, struct sparse_file* s) {
-    int size = sparse_file_len(s, true, false);
-    if (size <= 0) {
+    int64_t size = sparse_file_len(s, true, false);
+    if (size <= 0 || size > std::numeric_limits<uint32_t>::max()) {
         return -1;
     }
 
-    std::string cmd(android::base::StringPrintf("download:%08x", size));
+    std::string cmd(android::base::StringPrintf("download:%08" PRIx64, size));
     int r = _command_start(transport, cmd, size, 0);
     if (r < 0) {
         return -1;
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 9aab0ba..e9040df 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1383,7 +1383,7 @@
             mount_point = basename(fstab->recs[i].mount_point);
         }
 
-        fs_mgr_verity_ioctl_init(io, mount_point, 0);
+        fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, mount_point);
 
         const char* status;
         if (ioctl(fd, DM_TABLE_STATUS, io)) {
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 7824cfa..cf6b497 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -303,13 +303,14 @@
 
 static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd,
                               uint64_t image_size, const std::string& verity_table) {
-    fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG);
+    fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, dm_device_name);
 
     // The buffer consists of [dm_ioctl][dm_target_spec][verity_params].
     char* buffer = (char*)io;
 
     // Builds the dm_target_spec arguments.
     struct dm_target_spec* dm_target = (struct dm_target_spec*)&buffer[sizeof(struct dm_ioctl)];
+    io->flags = DM_READONLY_FLAG;
     io->target_count = 1;
     dm_target->status = 0;
     dm_target->sector_start = 0;
@@ -359,14 +360,14 @@
     alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
     struct dm_ioctl* io = (struct dm_ioctl*)buffer;
     const std::string mount_point(basename(fstab_entry->mount_point));
-    if (!fs_mgr_create_verity_device(io, mount_point, fd)) {
+    if (!fs_mgr_dm_create_device(io, mount_point, fd)) {
         LERROR << "Couldn't create verity device!";
         return false;
     }
 
     // Gets the name of the device file.
     std::string verity_blk_name;
-    if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) {
+    if (!fs_mgr_dm_get_device_name(io, mount_point, fd, &verity_blk_name)) {
         LERROR << "Couldn't get verity device number!";
         return false;
     }
@@ -385,7 +386,7 @@
     }
 
     // Activates the device.
-    if (!fs_mgr_resume_verity_table(io, mount_point, fd)) {
+    if (!fs_mgr_dm_resume_table(io, mount_point, fd)) {
         return false;
     }
 
diff --git a/fs_mgr/fs_mgr_dm_ioctl.cpp b/fs_mgr/fs_mgr_dm_ioctl.cpp
index 4cbd5a8..3a7fae4 100644
--- a/fs_mgr/fs_mgr_dm_ioctl.cpp
+++ b/fs_mgr/fs_mgr_dm_ioctl.cpp
@@ -23,21 +23,20 @@
 #include "fs_mgr_priv.h"
 #include "fs_mgr_priv_dm_ioctl.h"
 
-void fs_mgr_verity_ioctl_init(struct dm_ioctl* io, const std::string& name, unsigned flags) {
-    memset(io, 0, DM_BUF_SIZE);
-    io->data_size = DM_BUF_SIZE;
+void fs_mgr_dm_ioctl_init(struct dm_ioctl* io, size_t size, const std::string& name) {
+    memset(io, 0, size);
+    io->data_size = size;
     io->data_start = sizeof(struct dm_ioctl);
     io->version[0] = 4;
     io->version[1] = 0;
     io->version[2] = 0;
-    io->flags = flags | DM_READONLY_FLAG;
     if (!name.empty()) {
         strlcpy(io->name, name.c_str(), sizeof(io->name));
     }
 }
 
-bool fs_mgr_create_verity_device(struct dm_ioctl* io, const std::string& name, int fd) {
-    fs_mgr_verity_ioctl_init(io, name, 1);
+bool fs_mgr_dm_create_device(struct dm_ioctl* io, const std::string& name, int fd) {
+    fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
     if (ioctl(fd, DM_DEV_CREATE, io)) {
         PERROR << "Error creating device mapping";
         return false;
@@ -45,8 +44,8 @@
     return true;
 }
 
-bool fs_mgr_destroy_verity_device(struct dm_ioctl* io, const std::string& name, int fd) {
-    fs_mgr_verity_ioctl_init(io, name, 0);
+bool fs_mgr_dm_destroy_device(struct dm_ioctl* io, const std::string& name, int fd) {
+    fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
     if (ioctl(fd, DM_DEV_REMOVE, io)) {
         PERROR << "Error removing device mapping";
         return false;
@@ -54,13 +53,13 @@
     return true;
 }
 
-bool fs_mgr_get_verity_device_name(struct dm_ioctl* io, const std::string& name, int fd,
-                                   std::string* out_dev_name) {
+bool fs_mgr_dm_get_device_name(struct dm_ioctl* io, const std::string& name, int fd,
+                               std::string* out_dev_name) {
     FS_MGR_CHECK(out_dev_name != nullptr);
 
-    fs_mgr_verity_ioctl_init(io, name, 0);
+    fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
     if (ioctl(fd, DM_DEV_STATUS, io)) {
-        PERROR << "Error fetching verity device number";
+        PERROR << "Error fetching device-mapper device number";
         return false;
     }
 
@@ -70,10 +69,10 @@
     return true;
 }
 
-bool fs_mgr_resume_verity_table(struct dm_ioctl* io, const std::string& name, int fd) {
-    fs_mgr_verity_ioctl_init(io, name, 0);
+bool fs_mgr_dm_resume_table(struct dm_ioctl* io, const std::string& name, int fd) {
+    fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
     if (ioctl(fd, DM_DEV_SUSPEND, io)) {
-        PERROR << "Error activating verity device";
+        PERROR << "Error activating device table";
         return false;
     }
     return true;
diff --git a/fs_mgr/fs_mgr_priv_dm_ioctl.h b/fs_mgr/fs_mgr_priv_dm_ioctl.h
index a00a9c1..792475d 100644
--- a/fs_mgr/fs_mgr_priv_dm_ioctl.h
+++ b/fs_mgr/fs_mgr_priv_dm_ioctl.h
@@ -20,15 +20,15 @@
 #include <linux/dm-ioctl.h>
 #include <string>
 
-void fs_mgr_verity_ioctl_init(struct dm_ioctl* io, const std::string& name, unsigned flags);
+void fs_mgr_dm_ioctl_init(struct dm_ioctl* io, size_t size, const std::string& name);
 
-bool fs_mgr_create_verity_device(struct dm_ioctl* io, const std::string& name, int fd);
+bool fs_mgr_dm_create_device(struct dm_ioctl* io, const std::string& name, int fd);
 
-bool fs_mgr_destroy_verity_device(struct dm_ioctl* io, const std::string& name, int fd);
+bool fs_mgr_dm_destroy_device(struct dm_ioctl* io, const std::string& name, int fd);
 
-bool fs_mgr_get_verity_device_name(struct dm_ioctl* io, const std::string& name, int fd,
-                                   std::string* out_dev_name);
+bool fs_mgr_dm_get_device_name(struct dm_ioctl* io, const std::string& name, int fd,
+                               std::string* out_dev_name);
 
-bool fs_mgr_resume_verity_table(struct dm_ioctl* io, const std::string& name, int fd);
+bool fs_mgr_dm_resume_table(struct dm_ioctl* io, const std::string& name, int fd);
 
 #endif /* __CORE_FS_MGR_PRIV_DM_IOCTL_H */
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 896b603..fe41f8a 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -258,12 +258,13 @@
     char *buffer = (char*) io;
     size_t bufsize;
 
-    fs_mgr_verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG);
+    fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, name);
 
     struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
 
     // set tgt arguments
     io->target_count = 1;
+    io->flags = DM_READONLY_FLAG;
     tgt->status = 0;
     tgt->sector_start = 0;
     tgt->length = device_size / 512;
@@ -804,13 +805,13 @@
     }
 
     // create the device
-    if (!fs_mgr_create_verity_device(io, mount_point, fd)) {
+    if (!fs_mgr_dm_create_device(io, mount_point, fd)) {
         LERROR << "Couldn't create verity device!";
         goto out;
     }
 
     // get the name of the device file
-    if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) {
+    if (!fs_mgr_dm_get_device_name(io, mount_point, fd, &verity_blk_name)) {
         LERROR << "Couldn't get verity device number!";
         goto out;
     }
@@ -899,7 +900,7 @@
 loaded:
 
     // activate the device
-    if (!fs_mgr_resume_verity_table(io, mount_point, fd)) {
+    if (!fs_mgr_dm_resume_table(io, mount_point, fd)) {
         goto out;
     }
 
@@ -922,7 +923,7 @@
     if (!verified_at_boot) {
         free(fstab->blk_device);
         fstab->blk_device = strdup(verity_blk_name.c_str());
-    } else if (!fs_mgr_destroy_verity_device(io, mount_point, fd)) {
+    } else if (!fs_mgr_dm_destroy_device(io, mount_point, fd)) {
         LERROR << "Failed to remove verity device " << mount_point.c_str();
         goto out;
     }
diff --git a/healthd/OWNERS b/healthd/OWNERS
index 2375f7c..00df08a 100644
--- a/healthd/OWNERS
+++ b/healthd/OWNERS
@@ -1 +1,2 @@
+elsk@google.com
 toddpoynor@google.com
diff --git a/init/Android.bp b/init/Android.bp
index 70a4ac6..a31c5a5 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -180,6 +180,7 @@
         "util_test.cpp",
     ],
     static_libs: ["libinit"],
+    test_suites: ["device-tests"],
 }
 
 cc_benchmark {
diff --git a/init/README.md b/init/README.md
index b14521c..c08b07a 100644
--- a/init/README.md
+++ b/init/README.md
@@ -193,7 +193,7 @@
 
 `disabled`
 > This service will not automatically start with its class.
-  It must be explicitly started by name.
+  It must be explicitly started by name or by interface name.
 
 `file <path> <type>`
 > Open a file path and pass its fd to the launched process. _type_ must be
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index 379b4fa..c2cf573 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -32,12 +32,14 @@
 #include <mutex>
 #include <thread>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 
 using android::base::StringPrintf;
+using android::base::boot_clock;
 using namespace std::chrono_literals;
 
 namespace android {
@@ -50,9 +52,9 @@
 static bool g_bootcharting_finished;
 
 static long long get_uptime_jiffies() {
-  std::string uptime;
-  if (!android::base::ReadFileToString("/proc/uptime", &uptime)) return 0;
-  return 100LL * strtod(uptime.c_str(), NULL);
+    constexpr int64_t kNanosecondsPerJiffy = 10000000;
+    boot_clock::time_point uptime = boot_clock::now();
+    return uptime.time_since_epoch().count() / kNanosecondsPerJiffy;
 }
 
 static std::unique_ptr<FILE, decltype(&fclose)> fopen_unique(const char* filename,
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
index e6cc08a..4451ac8 100644
--- a/init/host_init_stubs.cpp
+++ b/init/host_init_stubs.cpp
@@ -49,6 +49,10 @@
 }
 
 // selinux.h
+bool SelinuxHasVendorInit() {
+    return true;
+}
+
 void SelabelInitialize() {}
 
 bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index ddfb7ae..ad48602 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -56,6 +56,7 @@
                            const std::string& source_context, const ucred& cr, std::string* error);
 
 // selinux.h
+bool SelinuxHasVendorInit();
 void SelabelInitialize();
 bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
 
diff --git a/init/init.cpp b/init/init.cpp
index 0d5690b..54bbb4b 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -31,6 +31,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <map>
+#include <memory>
+#include <optional>
+
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -43,9 +47,6 @@
 #include <private/android_filesystem_config.h>
 #include <selinux/android.h>
 
-#include <memory>
-#include <optional>
-
 #include "action_parser.h"
 #include "import_parser.h"
 #include "init_first_stage.h"
@@ -130,12 +131,31 @@
     }
 }
 
-void register_epoll_handler(int fd, void (*fn)()) {
+static std::map<int, std::function<void()>> epoll_handlers;
+
+void register_epoll_handler(int fd, std::function<void()> handler) {
+    auto[it, inserted] = epoll_handlers.emplace(fd, std::move(handler));
+    if (!inserted) {
+        LOG(ERROR) << "Cannot specify two epoll handlers for a given FD";
+        return;
+    }
     epoll_event ev;
     ev.events = EPOLLIN;
-    ev.data.ptr = reinterpret_cast<void*>(fn);
+    // std::map's iterators do not get invalidated until erased, so we use the pointer to the
+    // std::function in the map directly for epoll_ctl.
+    ev.data.ptr = reinterpret_cast<void*>(&it->second);
     if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
-        PLOG(ERROR) << "epoll_ctl failed";
+        PLOG(ERROR) << "epoll_ctl failed to add fd";
+        epoll_handlers.erase(fd);
+    }
+}
+
+void unregister_epoll_handler(int fd) {
+    if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr) == -1) {
+        PLOG(ERROR) << "epoll_ctl failed to remove fd";
+    }
+    if (epoll_handlers.erase(fd) != 1) {
+        LOG(ERROR) << "Attempting to remove epoll handler for FD without an existing handler";
     }
 }
 
@@ -334,8 +354,8 @@
     return Success();
 }
 
-static Result<Success> keychord_init_action(const BuiltinArguments& args) {
-    keychord_init();
+static Result<Success> KeychordInitAction(const BuiltinArguments& args) {
+    KeychordInit();
     return Success();
 }
 
@@ -752,7 +772,7 @@
     am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
     am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
     am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
-    am.QueueBuiltinAction(keychord_init_action, "keychord_init");
+    am.QueueBuiltinAction(KeychordInitAction, "KeychordInit");
     am.QueueBuiltinAction(console_init_action, "console_init");
 
     // Trigger all the boot actions to get us started.
@@ -809,7 +829,7 @@
         if (nr == -1) {
             PLOG(ERROR) << "epoll_wait failed";
         } else if (nr == 1) {
-            ((void (*)()) ev.data.ptr)();
+            std::invoke(*reinterpret_cast<std::function<void()>*>(ev.data.ptr));
         }
     }
 
diff --git a/init/init.h b/init/init.h
index d4a0e96..e7c4d8d 100644
--- a/init/init.h
+++ b/init/init.h
@@ -19,6 +19,7 @@
 
 #include <sys/types.h>
 
+#include <functional>
 #include <string>
 #include <vector>
 
@@ -42,7 +43,8 @@
 
 void property_changed(const std::string& name, const std::string& value);
 
-void register_epoll_handler(int fd, void (*fn)());
+void register_epoll_handler(int fd, std::function<void()> handler);
+void unregister_epoll_handler(int fd);
 
 bool start_waiting_for_property(const char *name, const char *value);
 
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index 0f4cc68..1b6e97e 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -118,17 +118,14 @@
 // -----------------
 FirstStageMount::FirstStageMount()
     : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
-    if (!device_tree_fstab_) {
-        // The client of FirstStageMount should check the existence of fstab in device-tree
-        // in advance, without parsing it. Reaching here means there is a FATAL error when
-        // parsing the fstab. So stop here to expose the failure.
-        LOG(FATAL) << "Failed to read fstab from device tree";
-        return;
-    }
-    // Stores device_tree_fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>)
-    // for easier manipulation later, e.g., range-base for loop.
-    for (int i = 0; i < device_tree_fstab_->num_entries; i++) {
-        mount_fstab_recs_.push_back(&device_tree_fstab_->recs[i]);
+    if (device_tree_fstab_) {
+        // Stores device_tree_fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>)
+        // for easier manipulation later, e.g., range-base for loop.
+        for (int i = 0; i < device_tree_fstab_->num_entries; i++) {
+            mount_fstab_recs_.push_back(&device_tree_fstab_->recs[i]);
+        }
+    } else {
+        LOG(INFO) << "Failed to read fstab from device tree";
     }
 }
 
@@ -141,8 +138,11 @@
 }
 
 bool FirstStageMount::DoFirstStageMount() {
-    // Nothing to mount.
-    if (mount_fstab_recs_.empty()) return true;
+    if (mount_fstab_recs_.empty()) {
+        // Nothing to mount.
+        LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
+        return true;
+    }
 
     if (!InitDevices()) return false;
 
@@ -482,12 +482,6 @@
         return true;
     }
 
-    // Firstly checks if device tree fstab entries are compatible.
-    if (!is_android_dt_value_expected("fstab/compatible", "android,fstab")) {
-        LOG(INFO) << "First stage mount skipped (missing/incompatible fstab in device tree)";
-        return true;
-    }
-
     std::unique_ptr<FirstStageMount> handle = FirstStageMount::Create();
     if (!handle) {
         LOG(ERROR) << "Failed to create FirstStageMount";
diff --git a/init/keychords.cpp b/init/keychords.cpp
index e686ce1..f55d2c4 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -16,13 +16,20 @@
 
 #include "keychords.h"
 
+#include <dirent.h>
 #include <fcntl.h>
-#include <stdlib.h>
-#include <sys/stat.h>
+#include <linux/input.h>
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
 #include <sys/types.h>
-#include <linux/keychord.h>
 #include <unistd.h>
 
+#include <algorithm>
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
+
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 
@@ -31,51 +38,87 @@
 namespace android {
 namespace init {
 
-static struct input_keychord *keychords = 0;
-static int keychords_count = 0;
-static int keychords_length = 0;
-static int keychord_fd = -1;
+namespace {
 
-void add_service_keycodes(Service* svc)
-{
-    struct input_keychord *keychord;
-    size_t i, size;
+int keychords_count;
 
-    if (!svc->keycodes().empty()) {
-        /* add a new keychord to the list */
-        size = sizeof(*keychord) + svc->keycodes().size() * sizeof(keychord->keycodes[0]);
-        keychords = (input_keychord*) realloc(keychords, keychords_length + size);
-        if (!keychords) {
-            PLOG(ERROR) << "could not allocate keychords";
-            keychords_length = 0;
-            keychords_count = 0;
-            return;
+struct KeychordEntry {
+    const std::vector<int> keycodes;
+    bool notified;
+    int id;
+
+    KeychordEntry(const std::vector<int>& keycodes, int id)
+        : keycodes(keycodes), notified(false), id(id) {}
+};
+
+std::vector<KeychordEntry> keychord_entries;
+
+// Bit management
+class KeychordMask {
+  private:
+    typedef unsigned int mask_t;
+    std::vector<mask_t> bits;
+    static constexpr size_t bits_per_byte = 8;
+
+  public:
+    explicit KeychordMask(size_t bit = 0) : bits((bit + sizeof(mask_t) - 1) / sizeof(mask_t), 0) {}
+
+    void SetBit(size_t bit, bool value = true) {
+        auto idx = bit / (bits_per_byte * sizeof(mask_t));
+        if (idx >= bits.size()) return;
+        if (value) {
+            bits[idx] |= mask_t(1) << (bit % (bits_per_byte * sizeof(mask_t)));
+        } else {
+            bits[idx] &= ~(mask_t(1) << (bit % (bits_per_byte * sizeof(mask_t))));
         }
-
-        keychord = (struct input_keychord *)((char *)keychords + keychords_length);
-        keychord->version = KEYCHORD_VERSION;
-        keychord->id = keychords_count + 1;
-        keychord->count = svc->keycodes().size();
-        svc->set_keychord_id(keychord->id);
-
-        for (i = 0; i < svc->keycodes().size(); i++) {
-            keychord->keycodes[i] = svc->keycodes()[i];
-        }
-        keychords_count++;
-        keychords_length += size;
-    }
-}
-
-static void handle_keychord() {
-    int ret;
-    __u16 id;
-
-    ret = read(keychord_fd, &id, sizeof(id));
-    if (ret != sizeof(id)) {
-        PLOG(ERROR) << "could not read keychord id";
-        return;
     }
 
+    bool GetBit(size_t bit) const {
+        auto idx = bit / (bits_per_byte * sizeof(mask_t));
+        return bits[idx] & (mask_t(1) << (bit % (bits_per_byte * sizeof(mask_t))));
+    }
+
+    size_t bytesize() const { return bits.size() * sizeof(mask_t); }
+    void* data() { return bits.data(); }
+    size_t size() const { return bits.size() * sizeof(mask_t) * bits_per_byte; }
+    void resize(size_t bit) {
+        auto idx = bit / (bits_per_byte * sizeof(mask_t));
+        if (idx >= bits.size()) {
+            bits.resize(idx + 1, 0);
+        }
+    }
+
+    operator bool() const {
+        for (size_t i = 0; i < bits.size(); ++i) {
+            if (bits[i]) return true;
+        }
+        return false;
+    }
+
+    KeychordMask operator&(const KeychordMask& rval) const {
+        auto len = std::min(bits.size(), rval.bits.size());
+        KeychordMask ret;
+        ret.bits.resize(len);
+        for (size_t i = 0; i < len; ++i) {
+            ret.bits[i] = bits[i] & rval.bits[i];
+        }
+        return ret;
+    }
+
+    void operator|=(const KeychordMask& rval) {
+        size_t len = rval.bits.size();
+        bits.resize(len);
+        for (size_t i = 0; i < len; ++i) {
+            bits[i] |= rval.bits[i];
+        }
+    }
+};
+
+KeychordMask keychord_current;
+
+constexpr char kDevicePath[] = "/dev/input";
+
+void HandleKeychord(int id) {
     // Only handle keychords if adb is enabled.
     std::string adb_enabled = android::base::GetProperty("init.svc.adbd", "");
     if (adb_enabled == "running") {
@@ -94,32 +137,125 @@
     }
 }
 
-void keychord_init() {
+void KeychordLambdaCheck() {
+    for (auto& e : keychord_entries) {
+        bool found = true;
+        for (auto& code : e.keycodes) {
+            if (!keychord_current.GetBit(code)) {
+                e.notified = false;
+                found = false;
+                break;
+            }
+        }
+        if (!found) continue;
+        if (e.notified) continue;
+        e.notified = true;
+        HandleKeychord(e.id);
+    }
+}
+
+void KeychordLambdaHandler(int fd) {
+    input_event event;
+    auto res = TEMP_FAILURE_RETRY(::read(fd, &event, sizeof(event)));
+    if ((res != sizeof(event)) || (event.type != EV_KEY)) return;
+    keychord_current.SetBit(event.code, event.value);
+    KeychordLambdaCheck();
+}
+
+bool KeychordGeteventEnable(int fd) {
+    static bool EviocsmaskSupported = true;
+
+    // Make sure it is an event channel, should pass this ioctl call
+    int version;
+    if (::ioctl(fd, EVIOCGVERSION, &version)) return false;
+
+    if (EviocsmaskSupported) {
+        KeychordMask mask(EV_KEY);
+        mask.SetBit(EV_KEY);
+        input_mask msg = {};
+        msg.type = EV_SYN;
+        msg.codes_size = mask.bytesize();
+        msg.codes_ptr = reinterpret_cast<uintptr_t>(mask.data());
+        if (::ioctl(fd, EVIOCSMASK, &msg) == -1) {
+            PLOG(WARNING) << "EVIOCSMASK not supported";
+            EviocsmaskSupported = false;
+        }
+    }
+
+    KeychordMask mask;
+    for (auto& e : keychord_entries) {
+        for (auto& code : e.keycodes) {
+            mask.resize(code);
+            mask.SetBit(code);
+        }
+    }
+
+    keychord_current.resize(mask.size());
+    KeychordMask available(mask.size());
+    auto res = ::ioctl(fd, EVIOCGBIT(EV_KEY, available.bytesize()), available.data());
+    if (res == -1) return false;
+    if (!(available & mask)) return false;
+
+    if (EviocsmaskSupported) {
+        input_mask msg = {};
+        msg.type = EV_KEY;
+        msg.codes_size = mask.bytesize();
+        msg.codes_ptr = reinterpret_cast<uintptr_t>(mask.data());
+        ::ioctl(fd, EVIOCSMASK, &msg);
+    }
+
+    KeychordMask set(mask.size());
+    res = ::ioctl(fd, EVIOCGKEY(res), set.data());
+    if (res > 0) {
+        keychord_current |= mask & available & set;
+        KeychordLambdaCheck();
+    }
+    register_epoll_handler(fd, [fd]() { KeychordLambdaHandler(fd); });
+    return true;
+}
+
+void GeteventOpenDevice(const std::string& device) {
+    auto fd = TEMP_FAILURE_RETRY(::open(device.c_str(), O_RDWR | O_CLOEXEC));
+    if (fd == -1) {
+        PLOG(ERROR) << "Can not open " << device;
+        return;
+    }
+    if (!KeychordGeteventEnable(fd)) {
+        ::close(fd);
+    }
+}
+
+void GeteventOpenDevice() {
+    std::unique_ptr<DIR, decltype(&closedir)> device(opendir(kDevicePath), closedir);
+    if (!device) return;
+
+    dirent* entry;
+    while ((entry = readdir(device.get()))) {
+        if (entry->d_name[0] == '.') continue;
+        std::string devname(kDevicePath);
+        devname += '/';
+        devname += entry->d_name;
+        GeteventOpenDevice(devname);
+    }
+}
+
+void AddServiceKeycodes(Service* svc) {
+    if (svc->keycodes().empty()) return;
+    for (auto& code : svc->keycodes()) {
+        if ((code < 0) || (code >= KEY_MAX)) return;
+    }
+    ++keychords_count;
+    keychord_entries.emplace_back(KeychordEntry(svc->keycodes(), keychords_count));
+    svc->set_keychord_id(keychords_count);
+}
+
+}  // namespace
+
+void KeychordInit() {
     for (const auto& service : ServiceList::GetInstance()) {
-        add_service_keycodes(service.get());
+        AddServiceKeycodes(service.get());
     }
-
-    // Nothing to do if no services require keychords.
-    if (!keychords) {
-        return;
-    }
-
-    keychord_fd = TEMP_FAILURE_RETRY(open("/dev/keychord", O_RDWR | O_CLOEXEC));
-    if (keychord_fd == -1) {
-        PLOG(ERROR) << "could not open /dev/keychord";
-        return;
-    }
-
-    int ret = write(keychord_fd, keychords, keychords_length);
-    if (ret != keychords_length) {
-        PLOG(ERROR) << "could not configure /dev/keychord " << ret;
-        close(keychord_fd);
-    }
-
-    free(keychords);
-    keychords = nullptr;
-
-    register_epoll_handler(keychord_fd, handle_keychord);
+    if (keychords_count) GeteventOpenDevice();
 }
 
 }  // namespace init
diff --git a/init/keychords.h b/init/keychords.h
index 1c34098..689a3b5 100644
--- a/init/keychords.h
+++ b/init/keychords.h
@@ -22,8 +22,7 @@
 namespace android {
 namespace init {
 
-void add_service_keycodes(Service* svc);
-void keychord_init();
+void KeychordInit();
 
 }  // namespace init
 }  // namespace android
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 99d3c83..c3100a5 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -59,6 +59,7 @@
 #include "init.h"
 #include "persistent_properties.h"
 #include "property_type.h"
+#include "selinux.h"
 #include "subcontext.h"
 #include "util.h"
 
@@ -542,7 +543,7 @@
     size_t flen = 0;
 
     const char* context = kInitContext.c_str();
-    if (GetIntProperty("ro.vndk.version", 28) >= 28) {
+    if (SelinuxHasVendorInit()) {
         for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
             if (StartsWith(filename, path_prefix)) {
                 context = secontext;
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 6aba9c1..0ba5c4a 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -55,12 +55,14 @@
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
 #include <android-base/unique_fd.h>
 #include <selinux/android.h>
 
 #include "log.h"
 #include "util.h"
 
+using android::base::ParseInt;
 using android::base::Timer;
 using android::base::unique_fd;
 
@@ -453,6 +455,31 @@
     selinux_set_callback(SELINUX_CB_LOG, cb);
 }
 
+// This function checks whether the sepolicy supports vendor init.
+bool SelinuxHasVendorInit() {
+    if (!IsSplitPolicyDevice()) {
+        // If this device does not split sepolicy files, vendor_init will be available in the latest
+        // monolithic sepolicy file.
+        return true;
+    }
+
+    std::string version;
+    if (!GetVendorMappingVersion(&version)) {
+        // Return true as the default if we failed to load the vendor sepolicy version.
+        return true;
+    }
+
+    int major_version;
+    std::string major_version_str(version, 0, version.find('.'));
+    if (!ParseInt(major_version_str, &major_version)) {
+        PLOG(ERROR) << "Failed to parse the vendor sepolicy major version " << major_version_str;
+        // Return true as the default if we failed to parse the major version.
+        return true;
+    }
+
+    return major_version >= 28;
+}
+
 // selinux_android_file_context_handle() takes on the order of 10+ms to run, so we want to cache
 // its value.  selinux_android_restorecon() also needs an sehandle for file context look up.  It
 // will create and store its own copy, but selinux_android_set_sehandle() can be used to provide
diff --git a/init/selinux.h b/init/selinux.h
index 7b880ec..30069b5 100644
--- a/init/selinux.h
+++ b/init/selinux.h
@@ -27,6 +27,7 @@
 void SelinuxRestoreContext();
 
 void SelinuxSetupKernelLogging();
+bool SelinuxHasVendorInit();
 
 void SelabelInitialize();
 bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 9c0c0bb..fdb4641 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -357,7 +357,7 @@
 static std::vector<Subcontext> subcontexts;
 
 std::vector<Subcontext>* InitializeSubcontexts() {
-    if (GetIntProperty("ro.vndk.version", 28) >= 28) {
+    if (SelinuxHasVendorInit()) {
         for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
             subcontexts.emplace_back(path_prefix, secontext);
         }
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 4bd01d2..11b8144 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -22,11 +22,6 @@
         "-Werror",
     ],
 
-    // The latest clang (r230699) does not allow SP/PC to be declared in inline asm lists.
-    clang_cflags: ["-Wno-inline-asm"],
-
-    include_dirs: ["external/libunwind/include/tdep"],
-
     target: {
         darwin: {
             enabled: false,
@@ -92,7 +87,6 @@
             shared_libs: [
                 "libbase",
                 "liblog",
-                "libunwind",
                 "libunwindstack",
                 "libdexfile",
             ],
@@ -183,12 +177,16 @@
         "art/runtime",
     ],
 
+    test_suites: ["device-tests"],
     data: [
         "testdata/arm/*",
         "testdata/arm64/*",
         "testdata/x86/*",
         "testdata/x86_64/*",
     ],
+    required: [
+        "libbacktrace_test",
+    ],
 }
 
 cc_benchmark {
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 6d00dc6..e823257 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -160,10 +160,20 @@
                 misc_undefined: ["integer"],
             },
         },
+
+        vendor: {
+            exclude_srcs: [
+                // qtaguid.cpp loads libnetd_client.so with dlopen().  Since
+                // the interface of libnetd_client.so may vary between AOSP
+                // releases, exclude qtaguid.cpp from the VNDK-SP variant.
+                "qtaguid.cpp",
+            ],
+        }
     },
 
     shared_libs: ["liblog"],
     header_libs: [
+        "libbase_headers",
         "libcutils_headers",
         "libutils_headers",
     ],
diff --git a/libcutils/ashmem-host.cpp b/libcutils/ashmem-host.cpp
index b2bec99..bb990d5 100644
--- a/libcutils/ashmem-host.cpp
+++ b/libcutils/ashmem-host.cpp
@@ -24,7 +24,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/libcutils/canned_fs_config.cpp b/libcutils/canned_fs_config.cpp
index 6b5763b..2772ef0 100644
--- a/libcutils/canned_fs_config.cpp
+++ b/libcutils/canned_fs_config.cpp
@@ -21,7 +21,6 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/libcutils/hashmap.cpp b/libcutils/hashmap.cpp
index 65b6ab1..10e3b25 100644
--- a/libcutils/hashmap.cpp
+++ b/libcutils/hashmap.cpp
@@ -21,7 +21,6 @@
 #include <cutils/threads.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdbool.h>
 #include <sys/types.h>
 
 typedef struct Entry Entry;
diff --git a/libcutils/include/cutils/sched_policy.h b/libcutils/include/cutils/sched_policy.h
index 4c1113b..cf91b76 100644
--- a/libcutils/include/cutils/sched_policy.h
+++ b/libcutils/include/cutils/sched_policy.h
@@ -40,16 +40,17 @@
 
 /* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
 typedef enum {
-    SP_DEFAULT    = -1,
+    SP_DEFAULT = -1,
     SP_BACKGROUND = 0,
     SP_FOREGROUND = 1,
-    SP_SYSTEM     = 2,  // can't be used with set_sched_policy()
-    SP_AUDIO_APP  = 3,
-    SP_AUDIO_SYS  = 4,
-    SP_TOP_APP    = 5,
-    SP_RT_APP     = 6,
+    SP_SYSTEM = 2,  // can't be used with set_sched_policy()
+    SP_AUDIO_APP = 3,
+    SP_AUDIO_SYS = 4,
+    SP_TOP_APP = 5,
+    SP_RT_APP = 6,
+    SP_RESTRICTED = 7,
     SP_CNT,
-    SP_MAX        = SP_CNT - 1,
+    SP_MAX = SP_CNT - 1,
     SP_SYSTEM_DEFAULT = SP_FOREGROUND,
 } SchedPolicy;
 
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index bbb150d..58b9f09 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -74,7 +74,8 @@
 #define ATRACE_TAG_ADB              (1<<22)
 #define ATRACE_TAG_VIBRATOR         (1<<23)
 #define ATRACE_TAG_AIDL             (1<<24)
-#define ATRACE_TAG_LAST             ATRACE_TAG_AIDL
+#define ATRACE_TAG_NNAPI            (1<<25)
+#define ATRACE_TAG_LAST             ATRACE_TAG_NNAPI
 
 // Reserved for initialization.
 #define ATRACE_TAG_NOT_READY        (1ULL<<63)
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 8209167..3be8ad0 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -130,6 +130,7 @@
 #define AID_INCIDENTD 1067       /* incidentd daemon */
 #define AID_SECURE_ELEMENT 1068  /* secure element subsystem */
 #define AID_LMKD 1069            /* low memory killer daemon */
+#define AID_LLKD 1070            /* live lock daemon */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/libcutils/sched_policy.cpp b/libcutils/sched_policy.cpp
index f5ce82f..3fa548f 100644
--- a/libcutils/sched_policy.cpp
+++ b/libcutils/sched_policy.cpp
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <android-base/macros.h>
 #include <log/log.h>
 
 /* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
@@ -57,6 +58,7 @@
 static int bg_cpuset_fd = -1;
 static int fg_cpuset_fd = -1;
 static int ta_cpuset_fd = -1; // special cpuset for top app
+static int rs_cpuset_fd = -1;  // special cpuset for screen off restrictions
 
 // File descriptors open to /dev/stune/../tasks, setup by initialize, or -1 on error
 static int bg_schedboost_fd = -1;
@@ -151,6 +153,8 @@
             system_bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
             filename = "/dev/cpuset/top-app/tasks";
             ta_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
+            filename = "/dev/cpuset/restricted/tasks";
+            rs_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
 
             if (schedboost_enabled()) {
                 filename = "/dev/stune/top-app/tasks";
@@ -308,6 +312,9 @@
     case SP_SYSTEM:
         fd = system_bg_cpuset_fd;
         break;
+    case SP_RESTRICTED:
+        fd = rs_cpuset_fd;
+        break;
     default:
         boost_fd = fd = -1;
         break;
@@ -454,20 +461,16 @@
 
 #endif
 
-const char *get_sched_policy_name(SchedPolicy policy)
-{
+const char* get_sched_policy_name(SchedPolicy policy) {
     policy = _policy(policy);
-    static const char * const strings[SP_CNT] = {
-       [SP_BACKGROUND] = "bg",
-       [SP_FOREGROUND] = "fg",
-       [SP_SYSTEM]     = "  ",
-       [SP_AUDIO_APP]  = "aa",
-       [SP_AUDIO_SYS]  = "as",
-       [SP_TOP_APP]    = "ta",
-       [SP_RT_APP]    = "rt",
+    static const char* const kSchedPolicyNames[] = {
+            [SP_BACKGROUND] = "bg", [SP_FOREGROUND] = "fg", [SP_SYSTEM] = "  ",
+            [SP_AUDIO_APP] = "aa",  [SP_AUDIO_SYS] = "as",  [SP_TOP_APP] = "ta",
+            [SP_RT_APP] = "rt",     [SP_RESTRICTED] = "rs",
     };
-    if ((policy < SP_CNT) && (strings[policy] != NULL))
-        return strings[policy];
-    else
+    static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
+    if (policy < SP_BACKGROUND || policy >= SP_CNT) {
         return "error";
+    }
+    return kSchedPolicyNames[policy];
 }
diff --git a/libcutils/tests/sched_policy_test.cpp b/libcutils/tests/sched_policy_test.cpp
index 173174a..5942ee5 100644
--- a/libcutils/tests/sched_policy_test.cpp
+++ b/libcutils/tests/sched_policy_test.cpp
@@ -60,6 +60,12 @@
     return sleepTimes[median];
 }
 
+static void AssertPolicy(SchedPolicy expected_policy) {
+    SchedPolicy current_policy;
+    ASSERT_EQ(0, get_sched_policy(0, &current_policy));
+    EXPECT_EQ(expected_policy, current_policy);
+}
+
 TEST(SchedPolicy, set_sched_policy) {
     if (!hasCapSysNice()) {
         GTEST_LOG_(INFO) << "skipping test that requires CAP_SYS_NICE";
@@ -76,23 +82,17 @@
     const unsigned int BG_FG_SLACK_FACTOR = 100;
 
     ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+    AssertPolicy(SP_BACKGROUND);
     auto bgSleepTime = medianSleepTime();
 
     ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
+    AssertPolicy(SP_FOREGROUND);
     auto fgSleepTime = medianSleepTime();
     ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR);
 }
 
-TEST(SchedPolicy, get_sched_policy) {
-    SchedPolicy policy;
-    ASSERT_EQ(0, get_sched_policy(0, &policy));
-
-    const char *policyName = get_sched_policy_name(policy);
-    EXPECT_NE(nullptr, policyName);
-    EXPECT_STRNE("error", policyName);
-
-    ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
-    SchedPolicy newPolicy;
-    ASSERT_EQ(0, get_sched_policy(0, &newPolicy));
-    EXPECT_EQ(SP_BACKGROUND, newPolicy);
+TEST(SchedPolicy, get_sched_policy_name) {
+    EXPECT_STREQ("bg", get_sched_policy_name(SP_BACKGROUND));
+    EXPECT_STREQ("error", get_sched_policy_name(SchedPolicy(-2)));
+    EXPECT_STREQ("error", get_sched_policy_name(SP_CNT));
 }
diff --git a/libcutils/trace-dev.inc b/libcutils/trace-dev.inc
index f95c6c5..c9580af 100644
--- a/libcutils/trace-dev.inc
+++ b/libcutils/trace-dev.inc
@@ -24,7 +24,6 @@
 #include <limits.h>
 #include <pthread.h>
 #include <stdatomic.h>
-#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
diff --git a/libkeyutils/Android.bp b/libkeyutils/Android.bp
index 0285259..f3593ff 100644
--- a/libkeyutils/Android.bp
+++ b/libkeyutils/Android.bp
@@ -13,4 +13,5 @@
     cflags: ["-Werror"],
     shared_libs: ["libkeyutils"],
     srcs: ["keyutils_test.cpp"],
+    test_suites: ["device-tests"],
 }
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index 619ee34..f164a19 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -89,6 +89,8 @@
             enabled: false,
         },
     },
+
+    test_suites: ["device-tests"],
 }
 
 cc_test {
@@ -103,4 +105,5 @@
         "libhwbinder",
         "libutils",
     ],
+    test_suites: ["device-tests"],
 }
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index 6549b8d..e6e17ce 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -29,6 +29,13 @@
     defaults: ["metricslogger_defaults"],
 }
 
+// static version of libmetricslogger, needed by a few art static binaries
+cc_library_static {
+    name: "libmetricslogger_static",
+    srcs: metricslogger_lib_src_files,
+    defaults: ["metricslogger_defaults"],
+}
+
 // metricslogger shared library, debug
 // -----------------------------------------------------------------------------
 cc_library_shared {
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index 189bc4b..2c76869 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <log/log_event_list.h>
 #include <cstdint>
 #include <string>
 
@@ -32,6 +33,34 @@
 // |value| in the field |field|.
 void LogMultiAction(int32_t category, int32_t field, const std::string& value);
 
+// Logs a Tron complex event.
+//
+// A complex event can include data in a structure not suppored by the other
+// log event types above.
+//
+// Note that instances of this class are single use. You must call Record()
+// to write the event to the event log.
+class ComplexEventLogger {
+  private:
+    android_log_event_list logger;
+
+  public:
+    // Create a complex event with category|category|.
+    explicit ComplexEventLogger(int category);
+    // Add tagged data to the event, with the given tag and integer value.
+    void AddTaggedData(int tag, int32_t value);
+    // Add tagged data to the event, with the given tag and string value.
+    void AddTaggedData(int tag, const std::string& value);
+    // Add tagged data to the event, with the given tag and integer value.
+    void AddTaggedData(int tag, int64_t value);
+    // Add tagged data to the event, with the given tag and float value.
+    void AddTaggedData(int tag, float value);
+    // Record this event. This method can only be used once per instance
+    // of ComplexEventLogger. Do not made any subsequent calls to AddTaggedData
+    // after recording an event.
+    void Record();
+};
+
 // TODO: replace these with the metric_logger.proto definitions
 enum {
     LOGBUILDER_CATEGORY = 757,
@@ -44,11 +73,23 @@
 
     ACTION_BOOT = 1098,
     FIELD_PLATFORM_REASON = 1099,
+
+    ACTION_HIDDEN_API_ACCESSED = 1391,
+    FIELD_HIDDEN_API_ACCESS_METHOD = 1392,
+    FIELD_HIDDEN_API_ACCESS_DENIED = 1393,
+    FIELD_HIDDEN_API_SIGNATURE = 1394,
 };
 
 enum {
     TYPE_ACTION = 4,
 };
 
+enum {
+    ACCESS_METHOD_NONE = 0,
+    ACCESS_METHOD_REFLECTION = 1,
+    ACCESS_METHOD_JNI = 2,
+    ACCESS_METHOD_LINKING = 3,
+};
+
 }  // namespace metricslogger
 }  // namespace android
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index fdc4407..912fa12 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -23,9 +23,14 @@
 
 namespace {
 
+#ifdef __ANDROID__
 EventTagMap* kEventTagMap = android_openEventTagMap(nullptr);
 const int kSysuiMultiActionTag = android_lookupEventTagNum(
     kEventTagMap, "sysui_multi_action", "(content|4)", ANDROID_LOG_UNKNOWN);
+#else
+// android_openEventTagMap does not work on host builds.
+const int kSysuiMultiActionTag = 0;
+#endif
 
 }  // namespace
 
@@ -53,5 +58,29 @@
         << field << value << LOG_ID_EVENTS;
 }
 
+ComplexEventLogger::ComplexEventLogger(int category) : logger(kSysuiMultiActionTag) {
+    logger << LOGBUILDER_CATEGORY << category;
+}
+
+void ComplexEventLogger::AddTaggedData(int tag, int32_t value) {
+    logger << tag << value;
+}
+
+void ComplexEventLogger::AddTaggedData(int tag, const std::string& value) {
+    logger << tag << value;
+}
+
+void ComplexEventLogger::AddTaggedData(int tag, int64_t value) {
+    logger << tag << value;
+}
+
+void ComplexEventLogger::AddTaggedData(int tag, float value) {
+    logger << tag << value;
+}
+
+void ComplexEventLogger::Record() {
+    logger << LOG_ID_EVENTS;
+}
+
 }  // namespace metricslogger
 }  // namespace android
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 83b0a7f..b35882c 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -83,4 +83,6 @@
             suffix: "64",
         },
     },
+
+    test_suites: ["device-tests"],
 }
diff --git a/libsparse/include/sparse/sparse.h b/libsparse/include/sparse/sparse.h
index 356f65f..1b91ead 100644
--- a/libsparse/include/sparse/sparse.h
+++ b/libsparse/include/sparse/sparse.h
@@ -18,6 +18,7 @@
 #define _LIBSPARSE_SPARSE_H_
 
 #include <stdbool.h>
+#include <stddef.h>
 #include <stdint.h>
 
 #ifdef	__cplusplus
@@ -26,6 +27,11 @@
 
 struct sparse_file;
 
+// The callbacks in sparse_file_callback() and sparse_file_foreach_chunk() take
+// size_t as the length type (was `int` in past). This allows clients to keep
+// their codes compatibile with both versions as needed.
+#define	SPARSE_CALLBACK_USES_SIZE_T
+
 /**
  * sparse_file_new - create a new sparse file cookie
  *
@@ -201,7 +207,7 @@
  * Returns 0 on success, negative errno on error.
  */
 int sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
-		int (*write)(void *priv, const void *data, int len), void *priv);
+		int (*write)(void *priv, const void *data, size_t len), void *priv);
 
 /**
  * sparse_file_foreach_chunk - call a callback for data blocks in sparse file
@@ -218,7 +224,7 @@
  * Returns 0 on success, negative errno on error.
  */
 int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
-	int (*write)(void *priv, const void *data, int len, unsigned int block,
+	int (*write)(void *priv, const void *data, size_t len, unsigned int block,
 		     unsigned int nr_blocks),
 	void *priv);
 /**
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index 51e60ef..002ad27 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -109,7 +109,7 @@
 struct output_file_callback {
 	struct output_file out;
 	void *priv;
-	int (*write)(void *priv, const void *buf, int len);
+	int (*write)(void *priv, const void *buf, size_t len);
 };
 
 #define to_output_file_callback(_o) \
@@ -634,7 +634,8 @@
 	return &outn->out;
 }
 
-struct output_file *output_file_open_callback(int (*write)(void *, const void *, int),
+struct output_file *output_file_open_callback(
+		int (*write)(void *, const void *, size_t),
 		void *priv, unsigned int block_size, int64_t len,
 		int gz __unused, int sparse, int chunks, int crc)
 {
diff --git a/libsparse/output_file.h b/libsparse/output_file.h
index b67e94e..690f610 100644
--- a/libsparse/output_file.h
+++ b/libsparse/output_file.h
@@ -27,7 +27,8 @@
 
 struct output_file *output_file_open_fd(int fd, unsigned int block_size, int64_t len,
 		int gz, int sparse, int chunks, int crc);
-struct output_file *output_file_open_callback(int (*write)(void *, const void *, int),
+struct output_file *output_file_open_callback(
+		int (*write)(void *, const void *, size_t),
 		void *priv, unsigned int block_size, int64_t len, int gz, int sparse,
 		int chunks, int crc);
 int write_data_chunk(struct output_file *out, unsigned int len, void *data);
diff --git a/libsparse/sparse.c b/libsparse/sparse.c
index b175860..466435f 100644
--- a/libsparse/sparse.c
+++ b/libsparse/sparse.c
@@ -179,7 +179,7 @@
 }
 
 int sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
-		int (*write)(void *priv, const void *data, int len), void *priv)
+		int (*write)(void *priv, const void *data, size_t len), void *priv)
 {
 	int ret;
 	int chunks;
@@ -203,11 +203,11 @@
 	void		*priv;
 	unsigned int	block;
 	unsigned int	nr_blocks;
-	int (*write)(void *priv, const void *data, int len, unsigned int block,
-		     unsigned int nr_blocks);
+	int (*write)(void *priv, const void *data, size_t len,
+		     unsigned int block, unsigned int nr_blocks);
 };
 
-static int foreach_chunk_write(void *priv, const void *data, int len)
+static int foreach_chunk_write(void *priv, const void *data, size_t len)
 {
 	struct chunk_data *chk = priv;
 
@@ -215,7 +215,7 @@
 }
 
 int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
-	int (*write)(void *priv, const void *data, int len, unsigned int block,
+	int (*write)(void *priv, const void *data, size_t len, unsigned int block,
 		     unsigned int nr_blocks),
 	void *priv)
 {
@@ -250,7 +250,7 @@
 	return ret;
 }
 
-static int out_counter_write(void *priv, const void *data __unused, int len)
+static int out_counter_write(void *priv, const void *data __unused, size_t len)
 {
 	int64_t *count = priv;
 	*count += len;
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 6868f18..d411cee 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -186,6 +186,7 @@
         "libgmock",
     ],
 
+    test_suites: ["device-tests"],
     data: [
         "tests/files/elf32.xz",
         "tests/files/elf64.xz",
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index 27cab43..de22bde 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -197,4 +197,8 @@
   return true;
 }
 
+Regs* RegsArm::Clone() {
+  return new RegsArm(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index 4a2a6c4..a68f6e0 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -148,4 +148,8 @@
   return true;
 }
 
+Regs* RegsArm64::Clone() {
+  return new RegsArm64(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index c87e69b..2e6908c 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -173,4 +173,8 @@
   return true;
 }
 
+Regs* RegsMips::Clone() {
+  return new RegsMips(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 236a922..0b835a1 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -160,4 +160,8 @@
   return true;
 }
 
+Regs* RegsMips64::Clone() {
+  return new RegsMips64(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index f7e0614..9bb39d1 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -179,4 +179,8 @@
   return false;
 }
 
+Regs* RegsX86::Clone() {
+  return new RegsX86(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index 7d6ad86..ebad3f4 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -168,4 +168,8 @@
   return true;
 }
 
+Regs* RegsX86_64::Clone() {
+  return new RegsX86_64(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index 4bac473..878ced3 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -73,6 +73,8 @@
 
   uint16_t total_regs() { return total_regs_; }
 
+  virtual Regs* Clone() = 0;
+
   static ArchEnum CurrentArch();
   static Regs* RemoteGet(pid_t pid);
   static Regs* CreateFromUcontext(ArchEnum arch, void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
index 31e6797..44f6744 100644
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -50,6 +50,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index 0c45eba..a72f91f 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -50,6 +50,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
index 709f9e2..c9dd202 100644
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ b/libunwindstack/include/unwindstack/RegsMips.h
@@ -50,6 +50,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
index 1de83ea..7c42812 100644
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ b/libunwindstack/include/unwindstack/RegsMips64.h
@@ -50,6 +50,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
index 586c9d8..d19e449 100644
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -53,6 +53,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
index 061f479..dc9a220 100644
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -53,6 +53,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index ede16b3..d6ca9b7 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -58,6 +58,8 @@
   void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
   void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
 
+  Regs* Clone() override { return nullptr; }
+
  private:
   ArchEnum fake_arch_ = ARCH_UNKNOWN;
   uint64_t fake_pc_ = 0;
@@ -83,6 +85,8 @@
   bool SetPcFromReturnAddress(Memory*) override { return false; }
   bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
 
+  Regs* Clone() override { return nullptr; }
+
  private:
   uint64_t fake_pc_ = 0;
   uint64_t fake_sp_ = 0;
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index d15823e..90c3fe6 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -286,4 +286,39 @@
   EXPECT_EQ(ARCH_MIPS64, mips64_regs.Arch());
 }
 
+template <typename RegisterType>
+void clone_test(Regs* regs) {
+  RegisterType* register_values = reinterpret_cast<RegisterType*>(regs->RawData());
+  int num_regs = regs->total_regs();
+  for (int i = 0; i < num_regs; ++i) {
+    register_values[i] = i;
+  }
+
+  std::unique_ptr<Regs> clone(regs->Clone());
+  ASSERT_EQ(regs->total_regs(), clone->total_regs());
+  RegisterType* clone_values = reinterpret_cast<RegisterType*>(clone->RawData());
+  for (int i = 0; i < num_regs; ++i) {
+    EXPECT_EQ(register_values[i], clone_values[i]);
+    EXPECT_NE(&register_values[i], &clone_values[i]);
+  }
+}
+
+TEST_F(RegsTest, clone) {
+  std::vector<std::unique_ptr<Regs>> regs;
+  regs.emplace_back(new RegsArm());
+  regs.emplace_back(new RegsArm64());
+  regs.emplace_back(new RegsX86());
+  regs.emplace_back(new RegsX86_64());
+  regs.emplace_back(new RegsMips());
+  regs.emplace_back(new RegsMips64());
+
+  for (auto& r : regs) {
+    if (r->Is32Bit()) {
+      clone_test<uint32_t>(r.get());
+    } else {
+      clone_test<uint64_t>(r.get());
+    }
+  }
+}
+
 }  // namespace unwindstack
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 075fb86..6c06618 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -61,6 +61,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
 
     defaults: [
         "libziparchive_defaults",
@@ -92,6 +93,10 @@
     host_supported: true,
     defaults: ["libziparchive_flags"],
 
+    data: [
+        "testdata/**/*",
+    ],
+
     srcs: [
         "entry_name_utils_test.cc",
         "zip_archive_test.cc",
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index ad673dc..377479f 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -34,7 +34,7 @@
 #include <ziparchive/zip_archive.h>
 #include <ziparchive/zip_archive_stream_entry.h>
 
-static std::string test_data_dir;
+static std::string test_data_dir = android::base::GetExecutableDirectory() + "/testdata";
 
 static const std::string kMissingZip = "missing.zip";
 static const std::string kValidZip = "valid.zip";
@@ -729,41 +729,3 @@
     ASSERT_EQ(0u, writer.GetOutput().size());
   }
 }
-
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-
-  static struct option options[] = {{"test_data_dir", required_argument, nullptr, 't'},
-                                    {nullptr, 0, nullptr, 0}};
-
-  while (true) {
-    int option_index;
-    const int c = getopt_long_only(argc, argv, "", options, &option_index);
-    if (c == -1) {
-      break;
-    }
-
-    if (c == 't') {
-      test_data_dir = optarg;
-    }
-  }
-
-  if (test_data_dir.size() == 0) {
-    printf("Test data flag (--test_data_dir) required\n\n");
-    return -1;
-  }
-
-  if (test_data_dir[0] != '/') {
-    std::vector<char> cwd_buffer(1024);
-    const char* cwd = getcwd(cwd_buffer.data(), cwd_buffer.size() - 1);
-    if (cwd == nullptr) {
-      printf("Cannot get current working directory, use an absolute path instead, was %s\n\n",
-             test_data_dir.c_str());
-      return -2;
-    }
-    test_data_dir = '/' + test_data_dir;
-    test_data_dir = cwd + test_data_dir;
-  }
-
-  return RUN_ALL_TESTS();
-}
diff --git a/llkd/Android.bp b/llkd/Android.bp
new file mode 100644
index 0000000..a6edd26
--- /dev/null
+++ b/llkd/Android.bp
@@ -0,0 +1,42 @@
+cc_library_headers {
+    name: "llkd_headers",
+
+    export_include_dirs: ["include"],
+}
+
+cc_library_static {
+    name: "libllkd",
+
+    srcs: [
+        "libllkd.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+
+    export_include_dirs: ["include"],
+
+    cflags: ["-Werror"],
+}
+
+cc_binary {
+    name: "llkd",
+
+    srcs: [
+        "llkd.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+    static_libs: [
+        "libllkd",
+    ],
+    cflags: ["-Werror"],
+
+    init_rc: ["llkd.rc"],
+}
diff --git a/llkd/OWNERS b/llkd/OWNERS
new file mode 100644
index 0000000..b6af537
--- /dev/null
+++ b/llkd/OWNERS
@@ -0,0 +1,2 @@
+salyzyn@google.com
+surenb@google.com
diff --git a/llkd/README.md b/llkd/README.md
new file mode 100644
index 0000000..b2ba2a2
--- /dev/null
+++ b/llkd/README.md
@@ -0,0 +1,117 @@
+Android Live-LocK Daemon
+========================
+
+Introduction
+------------
+
+Android Live-LocK Daemon (llkd) is used to catch kernel deadlocks and mitigate.
+
+Code is structured to allow integration into another service as either as part
+of the main loop, or spun off as a thread should that be necessary.  A default
+standalone implementation is provided by llkd component.
+
+The 'C' interface from libllkd component is thus:
+
+    #include "llkd.h"
+    bool llkInit(const char* threadname) /* return true if enabled */
+    unsigned llkCheckMillseconds(void)   /* ms to sleep for next check */
+
+If a threadname is provided, a thread will be automatically spawned, otherwise
+caller must call llkCheckMilliseconds in its main loop.  Function will return
+the period of time before the next expected call to this handler.
+
+Operations
+----------
+
+If a thread is in D or Z state with no forward progress for longer than
+ro.llk.timeout_ms, or ro.llk.[D|Z].timeout_ms, kill the process or parent
+process respectively.  If another scan shows the same process continues to
+exist, then have a confirmed live-lock condition and need to panic.  Panic
+the kernel in a manner to provide the greatest bugreporting details as to the
+condition.  Add a alarm self watchdog should llkd ever get locked up that is
+double the expected time to flow through the mainloop.  Sampling is every
+ro.llk_sample_ms.
+
+Default will not monitor init, or [kthreadd] and all that [kthreadd] spawns.
+This reduces the effectiveness of llkd by limiting its coverage.  If there is
+value in covering [kthreadd] spawned threads, the requirement will be that
+the drivers not remain in a persistent 'D' state, or that they have mechanisms
+to recover the thread should it be killed externally (this is good driver
+coding hygiene, a common request to add such to publicly reviewed kernel.org
+maintained drivers).  For instance use wait_event_interruptible() instead of
+wait_event().  The blacklists can be adjusted accordingly if these
+conditions are met to cover kernel components.
+
+An accompanying gTest set have been added, and will setup a persistent D or Z
+process, with and without forward progress, but not in a live-lock state
+because that would require a buggy kernel, or a module or kernel modification
+to stimulate.  The test will check that llkd will mitigate first by killing
+the appropriate process.  D state is setup by vfork() waiting for exec() in
+child process.  Z state is setup by fork() and an un-waited for child process.
+Should be noted that both of these conditions should never happen on Android
+on purpose, and llkd effectively sweeps up processes that create these
+conditions.  If the test can, it will reconfigure llkd to expedite the test
+duration by adjusting the ro.llk.* Android properties.  Tests run the D state
+with some scheduling progress to ensure that ABA checking prevents false
+triggers. If 100% reliable ABA on platform, then ro.llk.killtest can be
+set to false; however this will result in some of the unit tests to panic
+kernel instead of deal with more graceful kill operation.
+
+Android Properties
+------------------
+
+Android Properties llkd respond to (<prop>_ms parms are in milliseconds):
+
+#### ro.config.low_ram
+default false, if true do not sysrq t (dump all threads).
+
+#### ro.llk.enable
+default false, allow live-lock daemon to be enabled.
+
+#### llk.enable
+default ro.llk.enable, and evaluated for eng.
+
+#### ro.khungtask.enable
+default false, allow [khungtask] daemon to be enabled.
+
+#### khungtask.enable
+default ro.khungtask.enable and evaluated for eng.
+
+#### ro.llk.mlockall
+default false, enable call to mlockall().
+
+#### ro.khungtask.timeout
+default value 12 minutes, [khungtask] maximum timelimit.
+
+#### ro.llk.timeout_ms
+default 10 minutes, D or Z maximum timelimit, double this value and it sets
+the alarm watchdog for llkd.
+
+#### ro.llk.D.timeout_ms
+default ro.llk.timeout_ms, D maximum timelimit.
+
+#### ro.llk.Z.timeout_ms
+default ro.llk.timeout_ms, Z maximum timelimit.
+
+#### ro.llk.check_ms
+default 2 minutes samples of threads for D or Z.
+
+#### ro.llk.blacklist.process
+default 0,1,2 (kernel, init and [kthreadd]) plus process names
+init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,
+[watchdogd],[watchdogd/0],...,[watchdogd/<get_nprocs-1>].
+
+#### ro.llk.blacklist.parent
+default 0,2 (kernel and [kthreadd]).
+
+#### ro.llk.blacklist.uid
+default <empty>, comma separated list of uid numbers or names.
+
+Architectural Concerns
+----------------------
+
+- Create kernel module and associated gTest to actually test panic.
+- Create gTest to test out blacklist (ro.llk.blacklist.<properties> generally
+  not be inputs).  Could require more test-only interfaces to libllkd.
+- Speed up gTest using something else than ro.llk.<properties>, which should
+  not be inputs.
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
new file mode 100644
index 0000000..e3ae4bb
--- /dev/null
+++ b/llkd/include/llkd.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 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 _LLKD_H_
+#define _LLKD_H_
+
+#ifndef LOG_TAG
+#define LOG_TAG "livelock"
+#endif
+
+#include <stdbool.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+bool llkInit(const char* threadname); /* threadname NULL, not spawned */
+unsigned llkCheckMilliseconds(void);
+
+/* clang-format off */
+#define LLK_ENABLE_WRITEABLE_PROPERTY  "llk.enable"
+#define LLK_ENABLE_PROPERTY            "ro." LLK_ENABLE_WRITEABLE_PROPERTY
+#define LLK_ENABLE_DEFAULT             false /* "eng" and userdebug true */
+#define KHT_ENABLE_WRITEABLE_PROPERTY  "khungtask.enable"
+#define KHT_ENABLE_PROPERTY            "ro." KHT_ENABLE_WRITEABLE_PROPERTY
+#define LLK_MLOCKALL_PROPERTY          "ro.llk.mlockall"
+#define LLK_MLOCKALL_DEFAULT           true
+#define LLK_KILLTEST_PROPERTY          "ro.llk.killtest"
+#define LLK_KILLTEST_DEFAULT           true
+#define LLK_TIMEOUT_MS_PROPERTY        "ro.llk.timeout_ms"
+#define KHT_TIMEOUT_PROPERTY           "ro.khungtask.timeout"
+#define LLK_D_TIMEOUT_MS_PROPERTY      "ro.llk.D.timeout_ms"
+#define LLK_Z_TIMEOUT_MS_PROPERTY      "ro.llk.Z.timeout_ms"
+#define LLK_CHECK_MS_PROPERTY          "ro.llk.check_ms"
+/* LLK_CHECK_MS_DEFAULT = actual timeout_ms / LLK_CHECKS_PER_TIMEOUT_DEFAULT */
+#define LLK_CHECKS_PER_TIMEOUT_DEFAULT 5
+#define LLK_BLACKLIST_PROCESS_PROPERTY "ro.llk.blacklist.process"
+#define LLK_BLACKLIST_PROCESS_DEFAULT  \
+    "0,1,2,init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
+#define LLK_BLACKLIST_PARENT_PROPERTY  "ro.llk.blacklist.parent"
+#define LLK_BLACKLIST_PARENT_DEFAULT   "0,2,[kthreadd]"
+#define LLK_BLACKLIST_UID_PROPERTY     "ro.llk.blacklist.uid"
+#define LLK_BLACKLIST_UID_DEFAULT      ""
+/* clang-format on */
+
+__END_DECLS
+
+#ifdef __cplusplus
+extern "C++" { /* In case this included wrapped with __BEGIN_DECLS */
+
+#include <chrono>
+
+__BEGIN_DECLS
+/* C++ code allowed to not specify threadname argument for this C linkage */
+bool llkInit(const char* threadname = nullptr);
+__END_DECLS
+std::chrono::milliseconds llkCheck(bool checkRunning = false);
+
+/* clang-format off */
+#define LLK_TIMEOUT_MS_DEFAULT  std::chrono::duration_cast<milliseconds>(std::chrono::minutes(10))
+#define LLK_TIMEOUT_MS_MINIMUM  std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(10))
+#define LLK_CHECK_MS_MINIMUM    std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(1))
+/* clang-format on */
+
+} /* extern "C++" */
+#endif /* __cplusplus */
+
+#endif /* _LLKD_H_ */
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
new file mode 100644
index 0000000..f357cc2
--- /dev/null
+++ b/llkd/libllkd.cpp
@@ -0,0 +1,1168 @@
+/*
+ * Copyright (C) 2018 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 "llkd.h"
+
+#include <ctype.h>
+#include <dirent.h>  // opendir() and readdir()
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <pwd.h>  // getpwuid()
+#include <signal.h>
+#include <stdint.h>
+#include <sys/cdefs.h>  // ___STRING, __predict_true() and _predict_false()
+#include <sys/mman.h>   // mlockall()
+#include <sys/prctl.h>
+#include <sys/stat.h>     // lstat()
+#include <sys/syscall.h>  // __NR_getdents64
+#include <sys/sysinfo.h>  // get_nprocs_conf()
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <chrono>
+#include <ios>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <cutils/android_get_control_file.h>
+#include <log/log_main.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+
+#define TASK_COMM_LEN 16  // internal kernel, not uapi, from .../linux/include/linux/sched.h
+
+using namespace std::chrono_literals;
+using namespace std::chrono;
+
+namespace {
+
+constexpr pid_t kernelPid = 0;
+constexpr pid_t initPid = 1;
+constexpr pid_t kthreaddPid = 2;
+
+constexpr char procdir[] = "/proc/";
+
+// Configuration
+milliseconds llkUpdate;                              // last check ms signature
+milliseconds llkCycle;                               // ms to next thread check
+bool llkEnable = LLK_ENABLE_DEFAULT;                 // llk daemon enabled
+bool llkRunning = false;                             // thread is running
+bool llkMlockall = LLK_MLOCKALL_DEFAULT;             // run mlocked
+bool llkTestWithKill = LLK_KILLTEST_DEFAULT;         // issue test kills
+milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;  // default timeout
+enum { llkStateD, llkStateZ, llkNumStates };         // state indexes
+milliseconds llkStateTimeoutMs[llkNumStates];        // timeout override for each detection state
+milliseconds llkCheckMs;                             // checking interval to inspect any
+                                                     // persistent live-locked states
+bool llkLowRam;                                      // ro.config.low_ram
+bool khtEnable = LLK_ENABLE_DEFAULT;                 // [khungtaskd] panic
+// [khungtaskd] should have a timeout beyond the granularity of llkTimeoutMs.
+// Provides a wide angle of margin b/c khtTimeout is also its granularity.
+seconds khtTimeout = duration_cast<seconds>(llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) /
+                                            LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+
+// Blacklist variables, initialized with comma separated lists of high false
+// positive and/or dangerous references, e.g. without self restart, for pid,
+// ppid, name and uid:
+
+// list of pids, or tids or names to skip. kernel pid (0), init pid (1),
+// [kthreadd] pid (2), ourselves, "init", "[kthreadd]", "lmkd", "llkd" or
+// combinations of watchdogd in kernel and user space.
+std::unordered_set<std::string> llkBlacklistProcess;
+// list of parent pids, comm or cmdline names to skip. default:
+// kernel pid (0), [kthreadd] (2), or ourselves, enforced and implied
+std::unordered_set<std::string> llkBlacklistParent;
+// list of uids, and uid names, to skip, default nothing
+std::unordered_set<std::string> llkBlacklistUid;
+
+class dir {
+  public:
+    enum level { proc, task, numLevels };
+
+  private:
+    int fd;
+    size_t available_bytes;
+    dirent* next;
+    // each directory level picked to be just north of 4K in size
+    static constexpr size_t buffEntries = 15;
+    static dirent buff[numLevels][buffEntries];
+
+    bool fill(enum level index) {
+        if (index >= numLevels) return false;
+        if (available_bytes != 0) return true;
+        if (__predict_false(fd < 0)) return false;
+        // getdents64 has no libc wrapper
+        auto rc = TEMP_FAILURE_RETRY(syscall(__NR_getdents64, fd, buff[index], sizeof(buff[0]), 0));
+        if (rc <= 0) return false;
+        available_bytes = rc;
+        next = buff[index];
+        return true;
+    }
+
+  public:
+    dir() : fd(-1), available_bytes(0), next(nullptr) {}
+
+    explicit dir(const char* directory)
+        : fd(__predict_true(directory != nullptr)
+                 ? ::open(directory, O_CLOEXEC | O_DIRECTORY | O_RDONLY)
+                 : -1),
+          available_bytes(0),
+          next(nullptr) {}
+
+    explicit dir(const std::string&& directory)
+        : fd(::open(directory.c_str(), O_CLOEXEC | O_DIRECTORY | O_RDONLY)),
+          available_bytes(0),
+          next(nullptr) {}
+
+    explicit dir(const std::string& directory)
+        : fd(::open(directory.c_str(), O_CLOEXEC | O_DIRECTORY | O_RDONLY)),
+          available_bytes(0),
+          next(nullptr) {}
+
+    // Don't need any copy or move constructors.
+    explicit dir(const dir& c) = delete;
+    explicit dir(dir& c) = delete;
+    explicit dir(dir&& c) = delete;
+
+    ~dir() {
+        if (fd >= 0) {
+            ::close(fd);
+        }
+    }
+
+    operator bool() const { return fd >= 0; }
+
+    void reset(void) {
+        if (fd >= 0) {
+            ::close(fd);
+            fd = -1;
+            available_bytes = 0;
+            next = nullptr;
+        }
+    }
+
+    dir& reset(const char* directory) {
+        reset();
+        // available_bytes will _always_ be zero here as its value is
+        // intimately tied to fd < 0 or not.
+        fd = ::open(directory, O_CLOEXEC | O_DIRECTORY | O_RDONLY);
+        return *this;
+    }
+
+    void rewind(void) {
+        if (fd >= 0) {
+            ::lseek(fd, off_t(0), SEEK_SET);
+            available_bytes = 0;
+            next = nullptr;
+        }
+    }
+
+    dirent* read(enum level index = proc, dirent* def = nullptr) {
+        if (!fill(index)) return def;
+        auto ret = next;
+        available_bytes -= next->d_reclen;
+        next = reinterpret_cast<dirent*>(reinterpret_cast<char*>(next) + next->d_reclen);
+        return ret;
+    }
+} llkTopDirectory;
+
+dirent dir::buff[dir::numLevels][dir::buffEntries];
+
+// helper functions
+
+bool llkIsMissingExeLink(pid_t tid) {
+    char c;
+    // CAP_SYS_PTRACE is required to prevent ret == -1, but ENOENT is signal
+    auto ret = ::readlink((procdir + std::to_string(tid) + "/exe").c_str(), &c, sizeof(c));
+    return (ret == -1) && (errno == ENOENT);
+}
+
+// Common routine where caller accepts empty content as error/passthrough.
+// Reduces the churn of reporting read errors in the callers.
+std::string ReadFile(std::string&& path) {
+    std::string content;
+    if (!android::base::ReadFileToString(path, &content)) {
+        PLOG(DEBUG) << "Read " << path << " failed";
+        content = "";
+    }
+    return content;
+}
+
+std::string llkProcGetName(pid_t tid, const char* node = "/cmdline") {
+    std::string content = ReadFile(procdir + std::to_string(tid) + node);
+    static constexpr char needles[] = " \t\r\n";  // including trailing nul
+    auto pos = content.find_first_of(needles, 0, sizeof(needles));
+    if (pos != std::string::npos) {
+        content.erase(pos);
+    }
+    return content;
+}
+
+uid_t llkProcGetUid(pid_t tid) {
+    // Get the process' uid.  The following read from /status is admittedly
+    // racy, prone to corruption due to shape-changes.  The consequences are
+    // not catastrophic as we sample a few times before taking action.
+    //
+    // If /loginuid worked on reliably, or on Android (all tasks report -1)...
+    // Android lmkd causes /cgroup to contain memory:/<dom>/uid_<uid>/pid_<pid>
+    // which is tighter, but also not reliable.
+    std::string content = ReadFile(procdir + std::to_string(tid) + "/status");
+    static constexpr char Uid[] = "\nUid:";
+    auto pos = content.find(Uid);
+    if (pos == std::string::npos) {
+        return -1;
+    }
+    pos += ::strlen(Uid);
+    while ((pos < content.size()) && ::isblank(content[pos])) {
+        ++pos;
+    }
+    content.erase(0, pos);
+    for (pos = 0; (pos < content.size()) && ::isdigit(content[pos]); ++pos) {
+        ;
+    }
+    // Content of form 'Uid:	0	0	0	0', newline is error
+    if ((pos >= content.size()) || !::isblank(content[pos])) {
+        return -1;
+    }
+    content.erase(pos);
+    uid_t ret;
+    if (!android::base::ParseInt(content, &ret, uid_t(0))) {
+        return -1;
+    }
+    return ret;
+}
+
+struct proc {
+    pid_t tid;                     // monitored thread id (in Z or D state).
+    nanoseconds schedUpdate;       // /proc/<tid>/sched "se.avg.lastUpdateTime",
+    uint64_t nrSwitches;           // /proc/<tid>/sched "nr_switches" for
+                                   // refined ABA problem detection, determine
+                                   // forward scheduling progress.
+    milliseconds update;           // llkUpdate millisecond signature of last.
+    milliseconds count;            // duration in state.
+    pid_t pid;                     // /proc/<pid> before iterating through
+                                   // /proc/<pid>/task/<tid> for threads.
+    pid_t ppid;                    // /proc/<tid>/stat field 4 parent pid.
+    uid_t uid;                     // /proc/<tid>/status Uid: field.
+    unsigned time;                 // sum of /proc/<tid>/stat field 14 utime &
+                                   // 15 stime for coarse ABA problem detection.
+    std::string cmdline;           // cached /cmdline content
+    char state;                    // /proc/<tid>/stat field 3: Z or D
+                                   // (others we do not monitor: S, R, T or ?)
+    char comm[TASK_COMM_LEN + 3];  // space for adding '[' and ']'
+    bool exeMissingValid;          // exeMissing has been cached
+    bool cmdlineValid;             // cmdline has been cached
+    bool updated;                  // cleared before monitoring pass.
+    bool killed;                   // sent a kill to this thread, next panic...
+
+    void setComm(const char* _comm) { strncpy(comm + 1, _comm, sizeof(comm) - 2); }
+
+    proc(pid_t tid, pid_t pid, pid_t ppid, const char* _comm, int time, char state)
+        : tid(tid),
+          schedUpdate(0),
+          nrSwitches(0),
+          update(llkUpdate),
+          count(0),
+          pid(pid),
+          ppid(ppid),
+          uid(-1),
+          time(time),
+          state(state),
+          exeMissingValid(false),
+          cmdlineValid(false),
+          updated(true),
+          killed(!llkTestWithKill) {
+        memset(comm, '\0', sizeof(comm));
+        setComm(_comm);
+    }
+
+    const char* getComm(void) {
+        if (comm[1] == '\0') {  // comm Valid?
+            strncpy(comm + 1, llkProcGetName(tid, "/comm").c_str(), sizeof(comm) - 2);
+        }
+        if (!exeMissingValid) {
+            if (llkIsMissingExeLink(tid)) {
+                comm[0] = '[';
+            }
+            exeMissingValid = true;
+        }
+        size_t len = strlen(comm + 1);
+        if (__predict_true(len < (sizeof(comm) - 1))) {
+            if (comm[0] == '[') {
+                if ((comm[len] != ']') && __predict_true(len < (sizeof(comm) - 2))) {
+                    comm[++len] = ']';
+                    comm[++len] = '\0';
+                }
+            } else {
+                if (comm[len] == ']') {
+                    comm[len] = '\0';
+                }
+            }
+        }
+        return &comm[comm[0] != '['];
+    }
+
+    const char* getCmdline(void) {
+        if (!cmdlineValid) {
+            cmdline = llkProcGetName(tid);
+            cmdlineValid = true;
+        }
+        return cmdline.c_str();
+    }
+
+    uid_t getUid(void) {
+        if (uid <= 0) {  // Churn on root user, because most likely to setuid()
+            uid = llkProcGetUid(tid);
+        }
+        return uid;
+    }
+
+    void reset(void) {  // reset cache, if we detected pid rollover
+        uid = -1;
+        state = '?';
+        cmdline = "";
+        comm[0] = '\0';
+        exeMissingValid = false;
+        cmdlineValid = false;
+    }
+};
+
+std::unordered_map<pid_t, proc> tids;
+
+// Check range and setup defaults, in order of propagation:
+//     llkTimeoutMs
+//     llkCheckMs
+//     ...
+// KISS to keep it all self-contained, and called multiple times as parameters
+// are interpreted so that defaults, llkCheckMs and llkCycle make sense.
+void llkValidate() {
+    if (llkTimeoutMs == 0ms) {
+        llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;
+    }
+    llkTimeoutMs = std::max(llkTimeoutMs, LLK_TIMEOUT_MS_MINIMUM);
+    if (llkCheckMs == 0ms) {
+        llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
+    }
+    llkCheckMs = std::min(llkCheckMs, llkTimeoutMs);
+
+    for (size_t state = 0; state < ARRAY_SIZE(llkStateTimeoutMs); ++state) {
+        if (llkStateTimeoutMs[state] == 0ms) {
+            llkStateTimeoutMs[state] = llkTimeoutMs;
+        }
+        llkStateTimeoutMs[state] =
+            std::min(std::max(llkStateTimeoutMs[state], LLK_TIMEOUT_MS_MINIMUM), llkTimeoutMs);
+        llkCheckMs = std::min(llkCheckMs, llkStateTimeoutMs[state]);
+    }
+
+    llkCheckMs = std::max(llkCheckMs, LLK_CHECK_MS_MINIMUM);
+    if (llkCycle == 0ms) {
+        llkCycle = llkCheckMs;
+    }
+    llkCycle = std::min(llkCycle, llkCheckMs);
+}
+
+milliseconds llkGetTimespecDiffMs(timespec* from, timespec* to) {
+    return duration_cast<milliseconds>(seconds(to->tv_sec - from->tv_sec)) +
+           duration_cast<milliseconds>(nanoseconds(to->tv_nsec - from->tv_nsec));
+}
+
+std::string llkProcGetName(pid_t tid, const char* comm, const char* cmdline) {
+    if ((cmdline != nullptr) && (*cmdline != '\0')) {
+        return cmdline;
+    }
+    if ((comm != nullptr) && (*comm != '\0')) {
+        return comm;
+    }
+
+    // UNLIKELY! Here because killed before we kill it?
+    // Assume change is afoot, do not call llkTidAlloc
+
+    // cmdline ?
+    std::string content = llkProcGetName(tid);
+    if (content.size() != 0) {
+        return content;
+    }
+    // Comm instead?
+    content = llkProcGetName(tid, "/comm");
+    if (llkIsMissingExeLink(tid) && (content.size() != 0)) {
+        return '[' + content + ']';
+    }
+    return content;
+}
+
+int llkKillOneProcess(pid_t pid, char state, pid_t tid, const char* tcomm = nullptr,
+                      const char* tcmdline = nullptr, const char* pcomm = nullptr,
+                      const char* pcmdline = nullptr) {
+    std::string forTid;
+    if (tid != pid) {
+        forTid = " for '" + llkProcGetName(tid, tcomm, tcmdline) + "' (" + std::to_string(tid) + ")";
+    }
+    LOG(INFO) << "Killing '" << llkProcGetName(pid, pcomm, pcmdline) << "' (" << pid
+              << ") to check forward scheduling progress in " << state << " state" << forTid;
+    // CAP_KILL required
+    errno = 0;
+    auto r = ::kill(pid, SIGKILL);
+    if (r) {
+        PLOG(ERROR) << "kill(" << pid << ")=" << r << ' ';
+    }
+
+    return r;
+}
+
+// Kill one process
+int llkKillOneProcess(pid_t pid, proc* tprocp) {
+    return llkKillOneProcess(pid, tprocp->state, tprocp->tid, tprocp->getComm(),
+                             tprocp->getCmdline());
+}
+
+// Kill one process specified by kprocp
+int llkKillOneProcess(proc* kprocp, proc* tprocp) {
+    if (kprocp == nullptr) {
+        return -2;
+    }
+
+    return llkKillOneProcess(kprocp->tid, tprocp->state, tprocp->tid, tprocp->getComm(),
+                             tprocp->getCmdline(), kprocp->getComm(), kprocp->getCmdline());
+}
+
+// Acquire file descriptor from environment, or open and cache it.
+// NB: cache is unnecessary in our current context, pedantically
+//     required to prevent leakage of file descriptors in the future.
+int llkFileToWriteFd(const std::string& file) {
+    static std::unordered_map<std::string, int> cache;
+    auto search = cache.find(file);
+    if (search != cache.end()) return search->second;
+    auto fd = android_get_control_file(file.c_str());
+    if (fd >= 0) return fd;
+    fd = TEMP_FAILURE_RETRY(::open(file.c_str(), O_WRONLY | O_CLOEXEC));
+    if (fd >= 0) cache.emplace(std::make_pair(file, fd));
+    return fd;
+}
+
+// Wrap android::base::WriteStringToFile to use android_get_control_file.
+bool llkWriteStringToFile(const std::string& string, const std::string& file) {
+    auto fd = llkFileToWriteFd(file);
+    if (fd < 0) return false;
+    return android::base::WriteStringToFd(string, fd);
+}
+
+bool llkWriteStringToFileConfirm(const std::string& string, const std::string& file) {
+    auto fd = llkFileToWriteFd(file);
+    auto ret = (fd < 0) ? false : android::base::WriteStringToFd(string, fd);
+    std::string content;
+    if (!android::base::ReadFileToString(file, &content)) return ret;
+    return android::base::Trim(content) == string;
+}
+
+void llkPanicKernel(bool dump, pid_t tid, const char* state) __noreturn;
+void llkPanicKernel(bool dump, pid_t tid, const char* state) {
+    auto sysrqTriggerFd = llkFileToWriteFd("/proc/sysrq-trigger");
+    if (sysrqTriggerFd < 0) {
+        // DYB
+        llkKillOneProcess(initPid, 'R', tid);
+        // The answer to life, the universe and everything
+        ::exit(42);
+        // NOTREACHED
+    }
+    ::sync();
+    if (dump) {
+        // Show all locks that are held
+        android::base::WriteStringToFd("d", sysrqTriggerFd);
+        // This can trigger hardware watchdog, that is somewhat _ok_.
+        // But useless if pstore configured for <256KB, low ram devices ...
+        if (!llkLowRam) {
+            android::base::WriteStringToFd("t", sysrqTriggerFd);
+        }
+        ::usleep(200000);  // let everything settle
+    }
+    llkWriteStringToFile(std::string("SysRq : Trigger a crash : 'livelock,") + state + "'\n",
+                         "/dev/kmsg");
+    android::base::WriteStringToFd("c", sysrqTriggerFd);
+    // NOTREACHED
+    // DYB
+    llkKillOneProcess(initPid, 'R', tid);
+    // I sat at my desk, stared into the garden and thought '42 will do'.
+    // I typed it out. End of story
+    ::exit(42);
+    // NOTREACHED
+}
+
+void llkAlarmHandler(int) {
+    llkPanicKernel(false, ::getpid(), "alarm");
+}
+
+milliseconds GetUintProperty(const std::string& key, milliseconds def) {
+    return milliseconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
+                                                       static_cast<uint64_t>(def.max().count())));
+}
+
+seconds GetUintProperty(const std::string& key, seconds def) {
+    return seconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
+                                                  static_cast<uint64_t>(def.max().count())));
+}
+
+proc* llkTidLookup(pid_t tid) {
+    auto search = tids.find(tid);
+    if (search == tids.end()) {
+        return nullptr;
+    }
+    return &search->second;
+}
+
+void llkTidRemove(pid_t tid) {
+    tids.erase(tid);
+}
+
+proc* llkTidAlloc(pid_t tid, pid_t pid, pid_t ppid, const char* comm, int time, char state) {
+    auto it = tids.emplace(std::make_pair(tid, proc(tid, pid, ppid, comm, time, state)));
+    return &it.first->second;
+}
+
+std::string llkFormat(milliseconds ms) {
+    auto sec = duration_cast<seconds>(ms);
+    std::ostringstream s;
+    s << sec.count() << '.';
+    auto f = s.fill('0');
+    auto w = s.width(3);
+    s << std::right << (ms - sec).count();
+    s.width(w);
+    s.fill(f);
+    s << 's';
+    return s.str();
+}
+
+std::string llkFormat(seconds s) {
+    return std::to_string(s.count()) + 's';
+}
+
+std::string llkFormat(bool flag) {
+    return flag ? "true" : "false";
+}
+
+std::string llkFormat(const std::unordered_set<std::string>& blacklist) {
+    std::string ret;
+    for (auto entry : blacklist) {
+        if (ret.size()) {
+            ret += ",";
+        }
+        ret += entry;
+    }
+    return ret;
+}
+
+// We only officially support comma separators, but wetware being what they
+// are will take some liberty and I do not believe they should be punished.
+std::unordered_set<std::string> llkSplit(const std::string& s,
+                                         const std::string& delimiters = ", \t:") {
+    std::unordered_set<std::string> result;
+
+    size_t base = 0;
+    size_t found;
+    while (true) {
+        found = s.find_first_of(delimiters, base);
+        result.emplace(s.substr(base, found - base));
+        if (found == s.npos) break;
+        base = found + 1;
+    }
+    return result;
+}
+
+bool llkSkipName(const std::string& name,
+                 const std::unordered_set<std::string>& blacklist = llkBlacklistProcess) {
+    if ((name.size() == 0) || (blacklist.size() == 0)) {
+        return false;
+    }
+
+    return blacklist.find(name) != blacklist.end();
+}
+
+bool llkSkipPid(pid_t pid) {
+    return llkSkipName(std::to_string(pid), llkBlacklistProcess);
+}
+
+bool llkSkipPpid(pid_t ppid) {
+    return llkSkipName(std::to_string(ppid), llkBlacklistParent);
+}
+
+bool llkSkipUid(uid_t uid) {
+    // Match by number?
+    if (llkSkipName(std::to_string(uid), llkBlacklistUid)) {
+        return true;
+    }
+
+    // Match by name?
+    auto pwd = ::getpwuid(uid);
+    return (pwd != nullptr) && __predict_true(pwd->pw_name != nullptr) &&
+           __predict_true(pwd->pw_name[0] != '\0') && llkSkipName(pwd->pw_name, llkBlacklistUid);
+}
+
+bool getValidTidDir(dirent* dp, std::string* piddir) {
+    if (!::isdigit(dp->d_name[0])) {
+        return false;
+    }
+
+    // Corner case can not happen in reality b/c of above ::isdigit check
+    if (__predict_false(dp->d_type != DT_DIR)) {
+        if (__predict_false(dp->d_type == DT_UNKNOWN)) {  // can't b/c procfs
+            struct stat st;
+            *piddir = procdir;
+            *piddir += dp->d_name;
+            return (lstat(piddir->c_str(), &st) == 0) && (st.st_mode & S_IFDIR);
+        }
+        return false;
+    }
+
+    *piddir = procdir;
+    *piddir += dp->d_name;
+    return true;
+}
+
+bool llkIsMonitorState(char state) {
+    return (state == 'Z') || (state == 'D');
+}
+
+// returns -1 if not found
+long long getSchedValue(const std::string& schedString, const char* key) {
+    auto pos = schedString.find(key);
+    if (pos == std::string::npos) {
+        return -1;
+    }
+    pos = schedString.find(':', pos);
+    if (__predict_false(pos == std::string::npos)) {
+        return -1;
+    }
+    while ((++pos < schedString.size()) && ::isblank(schedString[pos])) {
+        ;
+    }
+    long long ret;
+    if (!android::base::ParseInt(schedString.substr(pos), &ret, static_cast<long long>(0))) {
+        return -1;
+    }
+    return ret;
+}
+
+// Primary ABA mitigation watching last time schedule activity happened
+void llkCheckSchedUpdate(proc* procp, const std::string& piddir) {
+    // Audit finds /proc/<tid>/sched is just over 1K, and
+    // is rarely larger than 2K, even less on Android.
+    // For example, the "se.avg.lastUpdateTime" field we are
+    // interested in typically within the primary set in
+    // the first 1K.
+    //
+    // Proc entries can not be read >1K atomically via libbase,
+    // but if there are problems we assume at least a few
+    // samples of reads occur before we take any real action.
+    std::string schedString = ReadFile(piddir + "/sched");
+    if (schedString.size() == 0) {
+        // /schedstat is not as standardized, but in 3.1+
+        // Android devices, the third field is nr_switches
+        // from /sched:
+        schedString = ReadFile(piddir + "/schedstat");
+        if (schedString.size() == 0) {
+            return;
+        }
+        auto val = static_cast<unsigned long long>(-1);
+        if (((::sscanf(schedString.c_str(), "%*d %*d %llu", &val)) == 1) &&
+            (val != static_cast<unsigned long long>(-1)) && (val != 0) &&
+            (val != procp->nrSwitches)) {
+            procp->nrSwitches = val;
+            procp->count = 0ms;
+            procp->killed = !llkTestWithKill;
+        }
+        return;
+    }
+
+    auto val = getSchedValue(schedString, "\nse.avg.lastUpdateTime");
+    if (val == -1) {
+        val = getSchedValue(schedString, "\nse.svg.last_update_time");
+    }
+    if (val != -1) {
+        auto schedUpdate = nanoseconds(val);
+        if (schedUpdate != procp->schedUpdate) {
+            procp->schedUpdate = schedUpdate;
+            procp->count = 0ms;
+            procp->killed = !llkTestWithKill;
+        }
+    }
+
+    val = getSchedValue(schedString, "\nnr_switches");
+    if (val != -1) {
+        if (static_cast<uint64_t>(val) != procp->nrSwitches) {
+            procp->nrSwitches = val;
+            procp->count = 0ms;
+            procp->killed = !llkTestWithKill;
+        }
+    }
+}
+
+void llkLogConfig(void) {
+    LOG(INFO) << "ro.config.low_ram=" << llkFormat(llkLowRam) << "\n"
+              << LLK_ENABLE_PROPERTY "=" << llkFormat(llkEnable) << "\n"
+              << KHT_ENABLE_PROPERTY "=" << llkFormat(khtEnable) << "\n"
+              << LLK_MLOCKALL_PROPERTY "=" << llkFormat(llkMlockall) << "\n"
+              << LLK_KILLTEST_PROPERTY "=" << llkFormat(llkTestWithKill) << "\n"
+              << KHT_TIMEOUT_PROPERTY "=" << llkFormat(khtTimeout) << "\n"
+              << LLK_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkTimeoutMs) << "\n"
+              << LLK_D_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateD]) << "\n"
+              << LLK_Z_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateZ]) << "\n"
+              << LLK_CHECK_MS_PROPERTY "=" << llkFormat(llkCheckMs) << "\n"
+              << LLK_BLACKLIST_PROCESS_PROPERTY "=" << llkFormat(llkBlacklistProcess) << "\n"
+              << LLK_BLACKLIST_PARENT_PROPERTY "=" << llkFormat(llkBlacklistParent) << "\n"
+              << LLK_BLACKLIST_UID_PROPERTY "=" << llkFormat(llkBlacklistUid);
+}
+
+void* llkThread(void* obj) {
+    LOG(INFO) << "started";
+
+    std::string name = std::to_string(::gettid());
+    if (!llkSkipName(name)) {
+        llkBlacklistProcess.emplace(name);
+    }
+    name = static_cast<const char*>(obj);
+    prctl(PR_SET_NAME, name.c_str());
+    if (__predict_false(!llkSkipName(name))) {
+        llkBlacklistProcess.insert(name);
+    }
+    // No longer modifying llkBlacklistProcess.
+    llkRunning = true;
+    llkLogConfig();
+    while (llkRunning) {
+        ::usleep(duration_cast<microseconds>(llkCheck(true)).count());
+    }
+    // NOTREACHED
+    LOG(INFO) << "exiting";
+    return nullptr;
+}
+
+}  // namespace
+
+milliseconds llkCheck(bool checkRunning) {
+    if (!llkEnable || (checkRunning != llkRunning)) {
+        return milliseconds::max();
+    }
+
+    // Reset internal watchdog, which is a healthy engineering margin of
+    // double the maximum wait or cycle time for the mainloop that calls us.
+    //
+    // This alarm is effectively the live lock detection of llkd, as
+    // we understandably can not monitor ourselves otherwise.
+    ::alarm(duration_cast<seconds>(llkTimeoutMs * 2).count());
+
+    // kernel jiffy precision fastest acquisition
+    static timespec last;
+    timespec now;
+    ::clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
+    auto ms = llkGetTimespecDiffMs(&last, &now);
+    if (ms < llkCycle) {
+        return llkCycle - ms;
+    }
+    last = now;
+
+    LOG(VERBOSE) << "opendir(\"" << procdir << "\")";
+    if (__predict_false(!llkTopDirectory)) {
+        // gid containing AID_READPROC required
+        llkTopDirectory.reset(procdir);
+        if (__predict_false(!llkTopDirectory)) {
+            // Most likely reason we could be here is a resource limit.
+            // Keep our processing down to a minimum, but not so low that
+            // we do not recover in a timely manner should the issue be
+            // transitory.
+            LOG(DEBUG) << "opendir(\"" << procdir << "\") failed";
+            return llkTimeoutMs;
+        }
+    }
+
+    for (auto& it : tids) {
+        it.second.updated = false;
+    }
+
+    auto prevUpdate = llkUpdate;
+    llkUpdate += ms;
+    ms -= llkCycle;
+    auto myPid = ::getpid();
+    auto myTid = ::gettid();
+    for (auto dp = llkTopDirectory.read(); dp != nullptr; dp = llkTopDirectory.read()) {
+        std::string piddir;
+
+        if (!getValidTidDir(dp, &piddir)) {
+            continue;
+        }
+
+        // Get the process tasks
+        std::string taskdir = piddir + "/task/";
+        int pid = -1;
+        LOG(VERBOSE) << "+opendir(\"" << taskdir << "\")";
+        dir taskDirectory(taskdir);
+        if (__predict_false(!taskDirectory)) {
+            LOG(DEBUG) << "+opendir(\"" << taskdir << "\") failed";
+        }
+        for (auto tp = taskDirectory.read(dir::task, dp); tp != nullptr;
+             tp = taskDirectory.read(dir::task)) {
+            if (!getValidTidDir(tp, &piddir)) {
+                continue;
+            }
+
+            // Get the process stat
+            std::string stat = ReadFile(piddir + "/stat");
+            if (stat.size() == 0) {
+                continue;
+            }
+            unsigned tid = -1;
+            char pdir[TASK_COMM_LEN + 1];
+            char state = '?';
+            unsigned ppid = -1;
+            unsigned utime = -1;
+            unsigned stime = -1;
+            int dummy;
+            pdir[0] = '\0';
+            // tid should not change value
+            auto match = ::sscanf(
+                stat.c_str(),
+                "%u (%" ___STRING(
+                    TASK_COMM_LEN) "[^)]) %c %u %*d %*d %*d %*d %*d %*d %*d %*d %*d %u %u %d",
+                &tid, pdir, &state, &ppid, &utime, &stime, &dummy);
+            if (pid == -1) {
+                pid = tid;
+            }
+            LOG(VERBOSE) << "match " << match << ' ' << tid << " (" << pdir << ") " << state << ' '
+                         << ppid << " ... " << utime << ' ' << stime << ' ' << dummy;
+            if (match != 7) {
+                continue;
+            }
+
+            auto procp = llkTidLookup(tid);
+            if (procp == nullptr) {
+                procp = llkTidAlloc(tid, pid, ppid, pdir, utime + stime, state);
+            } else {
+                // comm can change ...
+                procp->setComm(pdir);
+                procp->updated = true;
+                // pid/ppid/tid wrap?
+                if (((procp->update != prevUpdate) && (procp->update != llkUpdate)) ||
+                    (procp->ppid != ppid) || (procp->pid != pid)) {
+                    procp->reset();
+                } else if (procp->time != (utime + stime)) {  // secondary ABA.
+                    // watching utime+stime granularity jiffy
+                    procp->state = '?';
+                }
+                procp->update = llkUpdate;
+                procp->pid = pid;
+                procp->ppid = ppid;
+                procp->time = utime + stime;
+                if (procp->state != state) {
+                    procp->count = 0ms;
+                    procp->killed = !llkTestWithKill;
+                    procp->state = state;
+                } else {
+                    procp->count += llkCycle;
+                }
+            }
+
+            // Filter checks in intuitive order of CPU cost to evaluate
+            // If tid unique continue, if ppid or pid unique break
+
+            if (pid == myPid) {
+                break;
+            }
+            if (!llkIsMonitorState(state)) {
+                continue;
+            }
+            if ((tid == myTid) || llkSkipPid(tid)) {
+                continue;
+            }
+            if (llkSkipPpid(ppid)) {
+                break;
+            }
+
+            if (llkSkipName(procp->getComm())) {
+                continue;
+            }
+            if (llkSkipName(procp->getCmdline())) {
+                break;
+            }
+
+            auto pprocp = llkTidLookup(ppid);
+            if (pprocp == nullptr) {
+                pprocp = llkTidAlloc(ppid, ppid, 0, "", 0, '?');
+            }
+            if ((pprocp != nullptr) && (llkSkipName(pprocp->getComm(), llkBlacklistParent) ||
+                                        llkSkipName(pprocp->getCmdline(), llkBlacklistParent))) {
+                break;
+            }
+
+            if ((llkBlacklistUid.size() != 0) && llkSkipUid(procp->getUid())) {
+                continue;
+            }
+
+            // ABA mitigation watching last time schedule activity happened
+            llkCheckSchedUpdate(procp, piddir);
+
+            // Can only fall through to here if registered D or Z state !!!
+            if (procp->count < llkStateTimeoutMs[(state == 'Z') ? llkStateZ : llkStateD]) {
+                LOG(VERBOSE) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->"
+                             << pid << "->" << tid << ' ' << procp->getComm();
+                continue;
+            }
+
+            // We have to kill it to determine difference between live lock
+            // and persistent state blocked on a resource.  Is there something
+            // wrong with a process that has no forward scheduling progress in
+            // Z or D?  Yes, generally means improper accounting in the
+            // process, but not always ...
+            //
+            // Whomever we hit with a test kill must accept the Android
+            // Aphorism that everything can be burned to the ground and
+            // must survive.
+            if (procp->killed == false) {
+                procp->killed = true;
+                // confirm: re-read uid before committing to a panic.
+                procp->uid = -1;
+                switch (state) {
+                    case 'Z':  // kill ppid to free up a Zombie
+                        // Killing init will kernel panic without diagnostics
+                        // so skip right to controlled kernel panic with
+                        // diagnostics.
+                        if (ppid == initPid) {
+                            break;
+                        }
+                        LOG(WARNING) << "Z " << llkFormat(procp->count) << ' ' << ppid << "->"
+                                     << pid << "->" << tid << ' ' << procp->getComm() << " [kill]";
+                        if ((llkKillOneProcess(pprocp, procp) >= 0) ||
+                            (llkKillOneProcess(ppid, procp) >= 0)) {
+                            continue;
+                        }
+                        break;
+
+                    case 'D':  // kill tid to free up an uninterruptible D
+                        // If ABA is doing its job, we would not need or
+                        // want the following.  Test kill is a Hail Mary
+                        // to make absolutely sure there is no forward
+                        // scheduling progress.  The cost when ABA is
+                        // not working is we kill a process that likes to
+                        // stay in 'D' state, instead of panicing the
+                        // kernel (worse).
+                        LOG(WARNING) << "D " << llkFormat(procp->count) << ' ' << pid << "->" << tid
+                                     << ' ' << procp->getComm() << " [kill]";
+                        if ((llkKillOneProcess(llkTidLookup(pid), procp) >= 0) ||
+                            (llkKillOneProcess(pid, 'D', tid) >= 0) ||
+                            (llkKillOneProcess(procp, procp) >= 0) ||
+                            (llkKillOneProcess(tid, 'D', tid) >= 0)) {
+                            continue;
+                        }
+                        break;
+                }
+            }
+            // We are here because we have confirmed kernel live-lock
+            LOG(ERROR) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->" << pid
+                       << "->" << tid << ' ' << procp->getComm() << " [panic]";
+            llkPanicKernel(true, tid, (state == 'Z') ? "zombie" : "driver");
+        }
+        LOG(VERBOSE) << "+closedir()";
+    }
+    llkTopDirectory.rewind();
+    LOG(VERBOSE) << "closedir()";
+
+    // garbage collection of old process references
+    for (auto p = tids.begin(); p != tids.end();) {
+        if (!p->second.updated) {
+            IF_ALOG(LOG_VERBOSE, LOG_TAG) {
+                std::string ppidCmdline = llkProcGetName(p->second.ppid, nullptr, nullptr);
+                if (ppidCmdline.size()) {
+                    ppidCmdline = "(" + ppidCmdline + ")";
+                }
+                std::string pidCmdline;
+                if (p->second.pid != p->second.tid) {
+                    pidCmdline = llkProcGetName(p->second.pid, nullptr, p->second.getCmdline());
+                    if (pidCmdline.size()) {
+                        pidCmdline = "(" + pidCmdline + ")";
+                    }
+                }
+                std::string tidCmdline =
+                    llkProcGetName(p->second.tid, p->second.getComm(), p->second.getCmdline());
+                if (tidCmdline.size()) {
+                    tidCmdline = "(" + tidCmdline + ")";
+                }
+                LOG(VERBOSE) << "thread " << p->second.ppid << ppidCmdline << "->" << p->second.pid
+                             << pidCmdline << "->" << p->second.tid << tidCmdline << " removed";
+            }
+            p = tids.erase(p);
+        } else {
+            ++p;
+        }
+    }
+    if (__predict_false(tids.empty())) {
+        llkTopDirectory.reset();
+    }
+
+    llkCycle = llkCheckMs;
+
+    timespec end;
+    ::clock_gettime(CLOCK_MONOTONIC_COARSE, &end);
+    auto milli = llkGetTimespecDiffMs(&now, &end);
+    LOG((milli > 10s) ? ERROR : (milli > 1s) ? WARNING : VERBOSE) << "sample " << llkFormat(milli);
+
+    // cap to minimum sleep for 1 second since last cycle
+    if (llkCycle < (ms + 1s)) {
+        return 1s;
+    }
+    return llkCycle - ms;
+}
+
+unsigned llkCheckMilliseconds() {
+    return duration_cast<milliseconds>(llkCheck()).count();
+}
+
+bool llkInit(const char* threadname) {
+    llkLowRam = android::base::GetBoolProperty("ro.config.low_ram", false);
+    if (!LLK_ENABLE_DEFAULT && android::base::GetBoolProperty("ro.debuggable", false)) {
+        llkEnable = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
+        khtEnable = android::base::GetProperty(KHT_ENABLE_PROPERTY, "eng") == "eng";
+    }
+    llkEnable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, llkEnable);
+    if (llkEnable && !llkTopDirectory.reset(procdir)) {
+        // Most likely reason we could be here is llkd was started
+        // incorrectly without the readproc permissions.  Keep our
+        // processing down to a minimum.
+        llkEnable = false;
+    }
+    khtEnable = android::base::GetBoolProperty(KHT_ENABLE_PROPERTY, khtEnable);
+    llkMlockall = android::base::GetBoolProperty(LLK_MLOCKALL_PROPERTY, llkMlockall);
+    llkTestWithKill = android::base::GetBoolProperty(LLK_KILLTEST_PROPERTY, llkTestWithKill);
+    // if LLK_TIMOUT_MS_PROPERTY was not set, we will use a set
+    // KHT_TIMEOUT_PROPERTY as co-operative guidance for the default value.
+    khtTimeout = GetUintProperty(KHT_TIMEOUT_PROPERTY, khtTimeout);
+    if (khtTimeout == 0s) {
+        khtTimeout = duration_cast<seconds>(llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) /
+                                            LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+    }
+    llkTimeoutMs =
+        khtTimeout * LLK_CHECKS_PER_TIMEOUT_DEFAULT / (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+    llkTimeoutMs = GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    llkValidate();  // validate llkTimeoutMs, llkCheckMs and llkCycle
+    llkStateTimeoutMs[llkStateD] = GetUintProperty(LLK_D_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    llkStateTimeoutMs[llkStateZ] = GetUintProperty(LLK_Z_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
+    llkValidate();  // validate all (effectively minus llkTimeoutMs)
+    std::string defaultBlacklistProcess(
+        std::to_string(kernelPid) + "," + std::to_string(initPid) + "," +
+        std::to_string(kthreaddPid) + "," + std::to_string(::getpid()) + "," +
+        std::to_string(::gettid()) + "," LLK_BLACKLIST_PROCESS_DEFAULT);
+    if (threadname) {
+        defaultBlacklistProcess += std::string(",") + threadname;
+    }
+    for (int cpu = 1; cpu < get_nprocs_conf(); ++cpu) {
+        defaultBlacklistProcess += ",[watchdog/" + std::to_string(cpu) + "]";
+    }
+    defaultBlacklistProcess =
+        android::base::GetProperty(LLK_BLACKLIST_PROCESS_PROPERTY, defaultBlacklistProcess);
+    llkBlacklistProcess = llkSplit(defaultBlacklistProcess);
+    if (!llkSkipName("[khungtaskd]")) {  // ALWAYS ignore as special
+        llkBlacklistProcess.emplace("[khungtaskd]");
+    }
+    llkBlacklistParent = llkSplit(android::base::GetProperty(
+        LLK_BLACKLIST_PARENT_PROPERTY, std::to_string(kernelPid) + "," + std::to_string(kthreaddPid) +
+                                           "," LLK_BLACKLIST_PARENT_DEFAULT));
+    llkBlacklistUid =
+        llkSplit(android::base::GetProperty(LLK_BLACKLIST_UID_PROPERTY, LLK_BLACKLIST_UID_DEFAULT));
+
+    // internal watchdog
+    ::signal(SIGALRM, llkAlarmHandler);
+
+    // kernel hung task configuration? Otherwise leave it as-is
+    if (khtEnable) {
+        // EUID must be AID_ROOT to write to /proc/sys/kernel/ nodes, there
+        // are no capability overrides.  For security reasons we do not want
+        // to run as AID_ROOT.  We may not be able to write them successfully,
+        // we will try, but the least we can do is read the values back to
+        // confirm expectations and report whether configured or not.
+        auto configured = llkWriteStringToFileConfirm(std::to_string(khtTimeout.count()),
+                                                      "/proc/sys/kernel/hung_task_timeout_secs");
+        if (configured) {
+            llkWriteStringToFile("65535", "/proc/sys/kernel/hung_task_warnings");
+            llkWriteStringToFile("65535", "/proc/sys/kernel/hung_task_check_count");
+            configured = llkWriteStringToFileConfirm("1", "/proc/sys/kernel/hung_task_panic");
+        }
+        if (configured) {
+            LOG(INFO) << "[khungtaskd] configured";
+        } else {
+            LOG(WARNING) << "[khungtaskd] not configurable";
+        }
+    }
+
+    bool logConfig = true;
+    if (llkEnable) {
+        if (llkMlockall &&
+            // MCL_ONFAULT pins pages as they fault instead of loading
+            // everything immediately all at once. (Which would be bad,
+            // because as of this writing, we have a lot of mapped pages we
+            // never use.) Old kernels will see MCL_ONFAULT and fail with
+            // EINVAL; we ignore this failure.
+            //
+            // N.B. read the man page for mlockall. MCL_CURRENT | MCL_ONFAULT
+            // pins ⊆ MCL_CURRENT, converging to just MCL_CURRENT as we fault
+            // in pages.
+
+            // CAP_IPC_LOCK required
+            mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && (errno != EINVAL)) {
+            PLOG(WARNING) << "mlockall failed ";
+        }
+
+        if (threadname) {
+            pthread_attr_t attr;
+
+            if (!pthread_attr_init(&attr)) {
+                sched_param param;
+
+                memset(&param, 0, sizeof(param));
+                pthread_attr_setschedparam(&attr, &param);
+                pthread_attr_setschedpolicy(&attr, SCHED_BATCH);
+                if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
+                    pthread_t thread;
+                    if (!pthread_create(&thread, &attr, llkThread, const_cast<char*>(threadname))) {
+                        // wait a second for thread to start
+                        for (auto retry = 50; retry && !llkRunning; --retry) {
+                            ::usleep(20000);
+                        }
+                        logConfig = !llkRunning;  // printed in llkd context?
+                    } else {
+                        LOG(ERROR) << "failed to spawn llkd thread";
+                    }
+                } else {
+                    LOG(ERROR) << "failed to detach llkd thread";
+                }
+                pthread_attr_destroy(&attr);
+            } else {
+                LOG(ERROR) << "failed to allocate attibutes for llkd thread";
+            }
+        }
+    } else {
+        LOG(DEBUG) << "[khungtaskd] left unconfigured";
+    }
+    if (logConfig) {
+        llkLogConfig();
+    }
+
+    return llkEnable;
+}
diff --git a/llkd/llkd.cpp b/llkd/llkd.cpp
new file mode 100644
index 0000000..f10253d
--- /dev/null
+++ b/llkd/llkd.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 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 "llkd.h"
+
+#include <sched.h>
+#include <unistd.h>
+
+#include <chrono>
+
+#include <android-base/logging.h>
+
+using namespace std::chrono;
+
+int main(int, char**) {
+    LOG(INFO) << "started";
+
+    bool enabled = llkInit();
+
+    // Would like this policy to be automatic as part of libllkd,
+    // but that would be presumptuous and bad side-effect.
+    struct sched_param param;
+    memset(&param, 0, sizeof(param));
+    sched_setscheduler(0, SCHED_BATCH, &param);
+
+    while (true) {
+        if (enabled) {
+            ::usleep(duration_cast<microseconds>(llkCheck()).count());
+        } else {
+            ::pause();
+        }
+    }
+    // NOTREACHED
+
+    LOG(INFO) << "exiting";
+    return 0;
+}
diff --git a/llkd/llkd.rc b/llkd/llkd.rc
new file mode 100644
index 0000000..e538cdb
--- /dev/null
+++ b/llkd/llkd.rc
@@ -0,0 +1,49 @@
+# eng default for ro.llk.enable and ro.khungtask.enable
+on property:ro.debuggable=*
+    setprop llk.enable ${ro.llk.enable:-0}
+    setprop khungtask.enable ${ro.khungtask.enable:-0}
+
+on property:ro.debuggable=1
+    setprop llk.enable ${ro.llk.enable:-1}
+    setprop khungtask.enable ${ro.khungtask.enable:-1}
+
+on property:ro.llk.enable=eng
+    setprop llk.enable ${ro.debuggable:-0}
+
+on property:ro.khungtask.enable=eng
+    setprop khungtask.enable ${ro.debuggable:-0}
+
+on property:llk.enable=1
+    setprop llk.enable true
+
+on property:llk.enable=0
+    setprop llk.enable false
+
+on property:khungtask.enable=1
+    setprop khungtask.enable true
+
+on property:khungtask.enable=0
+    setprop khungtask.enable false
+
+# Configure [khungtaskd]
+on property:khungtask.enable=true
+    write /proc/sys/kernel/hung_task_timeout_secs ${ro.khungtask.timeout:-720}
+    write /proc/sys/kernel/hung_task_warnings 65535
+    write /proc/sys/kernel/hung_task_check_count 65535
+    write /proc/sys/kernel/hung_task_panic 1
+
+on property:khungtask.enable=false
+    write /proc/sys/kernel/hung_task_panic 0
+
+on property:llk.enable=true
+    start llkd
+
+service llkd /system/bin/llkd
+    class late_start
+    disabled
+    user llkd
+    group llkd readproc
+    capabilities KILL IPC_LOCK
+    file /dev/kmsg w
+    file /proc/sysrq-trigger w
+    writepid /dev/cpuset/system-background/tasks
diff --git a/llkd/tests/Android.bp b/llkd/tests/Android.bp
new file mode 100644
index 0000000..6dd5938
--- /dev/null
+++ b/llkd/tests/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2018 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: "llkd_unit_test",
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+    header_libs: [
+        "llkd_headers",
+    ],
+
+    target: {
+        android: {
+            srcs: [
+                "llkd_test.cpp",
+            ],
+        },
+    },
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+
+    compile_multilib: "first",
+}
diff --git a/llkd/tests/llkd_test.cpp b/llkd/tests/llkd_test.cpp
new file mode 100644
index 0000000..3a15ff1
--- /dev/null
+++ b/llkd/tests/llkd_test.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2018 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 <signal.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <chrono>
+#include <iostream>
+#include <string>
+
+#include <android-base/properties.h>
+#include <gtest/gtest.h>
+#include <log/log_time.h>  // for MS_PER_SEC and US_PER_SEC
+
+#include "llkd.h"
+
+using namespace std::chrono;
+using namespace std::chrono_literals;
+
+namespace {
+
+milliseconds GetUintProperty(const std::string& key, milliseconds def) {
+    return milliseconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
+                                                       static_cast<uint64_t>(def.max().count())));
+}
+
+seconds GetUintProperty(const std::string& key, seconds def) {
+    return seconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
+                                                  static_cast<uint64_t>(def.max().count())));
+}
+
+// GTEST_LOG_(WARNING) output is fugly, this has much less noise
+// ToDo: look into fixing googletest to produce output that matches style of
+//       all the other status messages, and can switch off __line__ and
+//       __function__ noise
+#define GTEST_LOG_WARNING std::cerr << "[ WARNING  ] "
+#define GTEST_LOG_INFO std::cerr << "[   INFO   ] "
+
+// Properties is _not_ a high performance ABI!
+void rest() {
+    usleep(200000);
+}
+
+void execute(const char* command) {
+    if (getuid() || system(command)) {
+        system((std::string("su root ") + command).c_str());
+    }
+}
+
+seconds llkdSleepPeriod(char state) {
+    auto default_eng = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
+    auto default_enable = LLK_ENABLE_DEFAULT;
+    if (!LLK_ENABLE_DEFAULT && default_eng &&
+        android::base::GetBoolProperty("ro.debuggable", false)) {
+        default_enable = true;
+    }
+    default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
+    if (default_eng) {
+        GTEST_LOG_INFO << LLK_ENABLE_PROPERTY " defaults to \"eng\" thus "
+                       << (default_enable ? "true" : "false") << "\n";
+    }
+    // Hail Mary hope is unconfigured.
+    if ((GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, LLK_TIMEOUT_MS_DEFAULT) !=
+         duration_cast<milliseconds>(120s)) ||
+        (GetUintProperty(LLK_CHECK_MS_PROPERTY,
+                         LLK_TIMEOUT_MS_DEFAULT / LLK_CHECKS_PER_TIMEOUT_DEFAULT) !=
+         duration_cast<milliseconds>(10s))) {
+        execute("stop llkd");
+        rest();
+        std::string setprop("setprop ");
+        execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " false").c_str());
+        rest();
+        execute((setprop + LLK_TIMEOUT_MS_PROPERTY + " 120000").c_str());
+        rest();
+        execute((setprop + KHT_TIMEOUT_PROPERTY + " 130").c_str());
+        rest();
+        execute((setprop + LLK_CHECK_MS_PROPERTY + " 10000").c_str());
+        rest();
+        execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
+        rest();
+        execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " true").c_str());
+        rest();
+    }
+    default_enable = LLK_ENABLE_DEFAULT;
+    if (!LLK_ENABLE_DEFAULT && (android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng") &&
+        android::base::GetBoolProperty("ro.debuggable", false)) {
+        default_enable = true;
+    }
+    default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
+    if (default_enable) {
+        execute("start llkd");
+        rest();
+        GTEST_LOG_INFO << "llkd enabled\n";
+    } else {
+        GTEST_LOG_WARNING << "llkd disabled\n";
+    }
+
+    /* KISS follows llk_init() */
+    milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;
+    seconds khtTimeout = duration_cast<seconds>(
+        llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) / LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+    khtTimeout = GetUintProperty(KHT_TIMEOUT_PROPERTY, khtTimeout);
+    llkTimeoutMs =
+        khtTimeout * LLK_CHECKS_PER_TIMEOUT_DEFAULT / (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+    llkTimeoutMs = GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    if (llkTimeoutMs < LLK_TIMEOUT_MS_MINIMUM) {
+        llkTimeoutMs = LLK_TIMEOUT_MS_MINIMUM;
+    }
+    milliseconds llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
+    auto timeout = GetUintProperty(
+        (state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY : LLK_D_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    if (timeout < LLK_TIMEOUT_MS_MINIMUM) {
+        timeout = LLK_TIMEOUT_MS_MINIMUM;
+    }
+
+    if (llkCheckMs > timeout) {
+        llkCheckMs = timeout;
+    }
+    llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
+    timeout += llkCheckMs;
+    auto sec = duration_cast<seconds>(timeout);
+    if (sec == 0s) {
+        ++sec;
+    } else if (sec > 59s) {
+        GTEST_LOG_WARNING << "llkd is configured for about " << duration_cast<minutes>(sec).count()
+                          << " minutes to react\n";
+    }
+
+    // 33% margin for the test to naturally timeout waiting for llkd to respond
+    return (sec * 4 + 2s) / 3;
+}
+
+inline void waitForPid(pid_t child_pid) {
+    int wstatus;
+    ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
+    EXPECT_FALSE(WIFEXITED(wstatus)) << "[   INFO   ] exit=" << WEXITSTATUS(wstatus);
+    ASSERT_TRUE(WIFSIGNALED(wstatus));
+    ASSERT_EQ(WTERMSIG(wstatus), SIGKILL);
+}
+
+bool checkKill(const char* reason) {
+    if (android::base::GetBoolProperty(LLK_KILLTEST_PROPERTY, LLK_KILLTEST_DEFAULT)) {
+        return false;
+    }
+    auto bootreason = android::base::GetProperty("sys.boot.reason", "nothing");
+    if (bootreason == reason) {
+        GTEST_LOG_INFO << "Expected test result confirmed " << reason << "\n";
+        return true;
+    }
+    GTEST_LOG_WARNING << "Expected test result is " << reason << "\n";
+
+    // apct adjustment if needed (set LLK_KILLTEST_PROPERTY to "off" to allow test)
+    //
+    // if (android::base::GetProperty(LLK_KILLTEST_PROPERTY, "") == "false") {
+    //     GTEST_LOG_WARNING << "Bypassing test\n";
+    //     return true;
+    // }
+
+    return false;
+}
+
+}  // namespace
+
+// The tests that use this helper are to simulate processes stuck in 'D'
+// state that are experiencing forward scheduled progress. As such the
+// expectation is that llkd will _not_ perform any mitigations. The sleepfor
+// argument helps us set the amount of forward scheduler progress.
+static void llkd_driver_ABA(const microseconds sleepfor) {
+    const auto period = llkdSleepPeriod('D');
+    if (period <= sleepfor) {
+        GTEST_LOG_WARNING << "llkd configuration too short for "
+                          << duration_cast<milliseconds>(sleepfor).count() << "ms work cycle\n";
+        return;
+    }
+
+    auto child_pid = fork();
+    ASSERT_LE(0, child_pid);
+    int wstatus;
+    if (!child_pid) {
+        auto ratio = period / sleepfor;
+        ASSERT_LT(0, ratio);
+        // vfork() parent is uninterruptable D state waiting for child to exec()
+        while (--ratio > 0) {
+            auto driver_pid = vfork();
+            ASSERT_LE(0, driver_pid);
+            if (driver_pid) {  // parent
+                waitpid(driver_pid, &wstatus, 0);
+                if (!WIFEXITED(wstatus)) {
+                    exit(42);
+                }
+                if (WEXITSTATUS(wstatus) != 42) {
+                    exit(42);
+                }
+            } else {
+                usleep(sleepfor.count());
+                exit(42);
+            }
+        }
+        exit(0);
+    }
+    ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
+    EXPECT_TRUE(WIFEXITED(wstatus));
+    if (WIFEXITED(wstatus)) {
+        EXPECT_EQ(0, WEXITSTATUS(wstatus));
+    }
+    ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[   INFO   ] signo=" << WTERMSIG(wstatus);
+}
+
+TEST(llkd, driver_ABA_fast) {
+    llkd_driver_ABA(5ms);
+}
+
+TEST(llkd, driver_ABA_slow) {
+    llkd_driver_ABA(1s);
+}
+
+TEST(llkd, driver_ABA_glacial) {
+    llkd_driver_ABA(1min);
+}
+
+// Following tests must be last in this file to capture possible errant
+// kernel_panic mitigation failure.
+
+// The following tests simulate processes stick in 'Z' or 'D' state with
+// no forward scheduling progress, but interruptible. As such the expectation
+// is that llkd will perform kill mitigation and not progress to kernel_panic.
+
+TEST(llkd, zombie) {
+    if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
+        return;
+    }
+
+    const auto period = llkdSleepPeriod('Z');
+
+    /* Create a Persistent Zombie Process */
+    pid_t child_pid = fork();
+    ASSERT_LE(0, child_pid);
+    if (!child_pid) {
+        auto zombie_pid = fork();
+        ASSERT_LE(0, zombie_pid);
+        if (!zombie_pid) {
+            sleep(1);
+            exit(0);
+        }
+        sleep(period.count());
+        exit(42);
+    }
+
+    waitForPid(child_pid);
+}
+
+TEST(llkd, driver) {
+    if (checkKill("kernel_panic,sysrq,livelock,driver")) {
+        return;
+    }
+
+    const auto period = llkdSleepPeriod('D');
+
+    /* Create a Persistent Device Process */
+    auto child_pid = fork();
+    ASSERT_LE(0, child_pid);
+    if (!child_pid) {
+        // vfork() parent is uninterruptable D state waiting for child to exec()
+        auto driver_pid = vfork();
+        ASSERT_LE(0, driver_pid);
+        sleep(period.count());
+        exit(driver_pid ? 42 : 0);
+    }
+
+    waitForPid(child_pid);
+}
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 0983676..750761f 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -67,8 +67,9 @@
 # ZygoteInit class preloading ends:
 3030 boot_progress_preload_end (time|2|3)
 
-# Dalvik VM
+# Dalvik VM / ART
 20003 dvm_lock_sample (process|3),(main|1|5),(thread|3),(time|1|3),(file|3),(line|1|5),(ownerfile|3),(ownerline|1|5),(sample_percent|1|6)
+20004 art_hidden_api_access (access_method|1),(flags|1),(class|3),(member|3),(type_signature|3)
 
 75000 sqlite_mem_alarm_current (current|1|2)
 75001 sqlite_mem_alarm_max (max|1|2)
@@ -119,6 +120,9 @@
 70200 aggregation (aggregation time|2|3)
 70201 aggregation_test (field1|1|2),(field2|1|2),(field3|1|2),(field4|1|2),(field5|1|2)
 
+# gms refuses to register this log tag, b/30156345
+70220 gms_unknown
+
 # libc failure logging
 80100 bionic_event_memcpy_buffer_overflow (uid|1)
 80105 bionic_event_strcat_buffer_overflow (uid|1)
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index b76160d..27cd9a8 100755
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -112,7 +112,7 @@
 std::map<std::string, std::string> LogAudit::populateDenialMap() {
     std::ifstream bug_file("/system/etc/selinux/selinux_denial_metadata");
     std::string line;
-    // allocate a map for the static map pointer in logParse to keep track of,
+    // allocate a map for the static map pointer in auditParse to keep track of,
     // this function only runs once
     std::map<std::string, std::string> denial_to_bug;
     if (bug_file.good()) {
@@ -140,7 +140,8 @@
     return "";
 }
 
-void LogAudit::logParse(const std::string& string, std::string* bug_num) {
+void LogAudit::auditParse(const std::string& string, uid_t uid,
+                          std::string* bug_num) {
     if (!__android_log_is_debuggable()) {
         bug_num->assign("");
         return;
@@ -162,6 +163,11 @@
     } else {
         bug_num->assign("");
     }
+
+    if (uid >= AID_APP_START && uid <= AID_APP_END) {
+        bug_num->append(" app=");
+        bug_num->append(android::uidToName(uid));
+    }
 }
 
 int LogAudit::logPrint(const char* fmt, ...) {
@@ -190,8 +196,27 @@
     while ((cp = strstr(str, "  "))) {
         memmove(cp, cp + 1, strlen(cp + 1) + 1);
     }
+    pid_t pid = getpid();
+    pid_t tid = gettid();
+    uid_t uid = AID_LOGD;
+    static const char pid_str[] = " pid=";
+    char* pidptr = strstr(str, pid_str);
+    if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) {
+        cp = pidptr + sizeof(pid_str) - 1;
+        pid = 0;
+        while (isdigit(*cp)) {
+            pid = (pid * 10) + (*cp - '0');
+            ++cp;
+        }
+        tid = pid;
+        logbuf->wrlock();
+        uid = logbuf->pidToUid(pid);
+        logbuf->unlock();
+        memmove(pidptr, cp, strlen(cp) + 1);
+    }
+
     bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded ");
-    static std::string bug_metadata;
+    static std::string denial_metadata;
     if ((fdDmesg >= 0) && initialized) {
         struct iovec iov[4];
         static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
@@ -228,8 +253,8 @@
                     last_info ? sizeof(log_info) : sizeof(log_warning);
                 iov[1].iov_base = last_str;
                 iov[1].iov_len = strlen(last_str);
-                iov[2].iov_base = const_cast<char*>(bug_metadata.c_str());
-                iov[2].iov_len = bug_metadata.length();
+                iov[2].iov_base = const_cast<char*>(denial_metadata.c_str());
+                iov[2].iov_len = denial_metadata.length();
                 if (count > 1) {
                     iov[3].iov_base = const_cast<char*>(resume);
                     iov[3].iov_len = strlen(resume);
@@ -249,14 +274,14 @@
             last_info = info;
         }
         if (count == 0) {
-            logParse(str, &bug_metadata);
+            auditParse(str, uid, &denial_metadata);
             iov[0].iov_base = info ? const_cast<char*>(log_info)
                                    : const_cast<char*>(log_warning);
             iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
             iov[1].iov_base = str;
             iov[1].iov_len = strlen(str);
-            iov[2].iov_base = const_cast<char*>(bug_metadata.c_str());
-            iov[2].iov_len = bug_metadata.length();
+            iov[2].iov_base = const_cast<char*>(denial_metadata.c_str());
+            iov[2].iov_len = denial_metadata.length();
             iov[3].iov_base = const_cast<char*>(newline);
             iov[3].iov_len = strlen(newline);
 
@@ -269,9 +294,6 @@
         return 0;
     }
 
-    pid_t pid = getpid();
-    pid_t tid = gettid();
-    uid_t uid = AID_LOGD;
     log_time now;
 
     static const char audit_str[] = " audit(";
@@ -296,29 +318,13 @@
         now = log_time(CLOCK_REALTIME);
     }
 
-    static const char pid_str[] = " pid=";
-    char* pidptr = strstr(str, pid_str);
-    if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) {
-        cp = pidptr + sizeof(pid_str) - 1;
-        pid = 0;
-        while (isdigit(*cp)) {
-            pid = (pid * 10) + (*cp - '0');
-            ++cp;
-        }
-        tid = pid;
-        logbuf->wrlock();
-        uid = logbuf->pidToUid(pid);
-        logbuf->unlock();
-        memmove(pidptr, cp, strlen(cp) + 1);
-    }
-
     // log to events
 
     size_t str_len = strnlen(str, LOGGER_ENTRY_MAX_PAYLOAD);
     if (((fdDmesg < 0) || !initialized) && !hasMetadata(str, str_len))
-        logParse(str, &bug_metadata);
-    str_len = (str_len + bug_metadata.length() <= LOGGER_ENTRY_MAX_PAYLOAD)
-                  ? str_len + bug_metadata.length()
+        auditParse(str, uid, &denial_metadata);
+    str_len = (str_len + denial_metadata.length() <= LOGGER_ENTRY_MAX_PAYLOAD)
+                  ? str_len + denial_metadata.length()
                   : LOGGER_ENTRY_MAX_PAYLOAD;
     size_t message_len = str_len + sizeof(android_log_event_string_t);
 
@@ -331,10 +337,10 @@
             reinterpret_cast<android_log_event_string_t*>(buffer);
         event->header.tag = htole32(AUDITD_LOG_TAG);
         event->type = EVENT_TYPE_STRING;
-        event->length = htole32(message_len);
-        memcpy(event->data, str, str_len - bug_metadata.length());
-        memcpy(event->data + str_len - bug_metadata.length(),
-               bug_metadata.c_str(), bug_metadata.length());
+        event->length = htole32(str_len);
+        memcpy(event->data, str, str_len - denial_metadata.length());
+        memcpy(event->data + str_len - denial_metadata.length(),
+               denial_metadata.c_str(), denial_metadata.length());
 
         rc = logbuf->log(
             LOG_ID_EVENTS, now, uid, pid, tid, reinterpret_cast<char*>(event),
@@ -380,7 +386,8 @@
         prefix_len = LOGGER_ENTRY_MAX_PAYLOAD;
     }
     size_t suffix_len = strnlen(ecomm, LOGGER_ENTRY_MAX_PAYLOAD - prefix_len);
-    message_len = str_len + prefix_len + suffix_len + bug_metadata.length() + 2;
+    message_len =
+        str_len + prefix_len + suffix_len + denial_metadata.length() + 2;
 
     if (main) {  // begin scope for main buffer
         char newstr[message_len];
@@ -390,7 +397,7 @@
         strncpy(newstr + 1 + str_len, str, prefix_len);
         strncpy(newstr + 1 + str_len + prefix_len, ecomm, suffix_len);
         strncpy(newstr + 1 + str_len + prefix_len + suffix_len,
-                bug_metadata.c_str(), bug_metadata.length());
+                denial_metadata.c_str(), denial_metadata.length());
 
         rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
                          (message_len <= USHRT_MAX) ? (unsigned short)message_len
diff --git a/logd/LogAudit.h b/logd/LogAudit.h
index 5904966..c3d7a3e 100644
--- a/logd/LogAudit.h
+++ b/logd/LogAudit.h
@@ -48,7 +48,7 @@
     std::map<std::string, std::string> populateDenialMap();
     std::string denialParse(const std::string& denial, char terminator,
                             const std::string& search_term);
-    void logParse(const std::string& string, std::string* bug_num);
+    void auditParse(const std::string& string, uid_t uid, std::string* bug_num);
     int logPrint(const char* fmt, ...)
         __attribute__((__format__(__printf__, 2, 3)));
 };
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 7a7ac7d..ab980ac 100755
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -825,7 +825,7 @@
                          (unsigned short)n);
 
     // notify readers
-    if (!rc) {
+    if (rc > 0) {
         reader->notifyNewLog(static_cast<log_mask_t>(1 << LOG_ID_KERNEL));
     }
 
diff --git a/logd/main.cpp b/logd/main.cpp
index 4af0d21..606aa63 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -33,7 +33,6 @@
 #include <syslog.h>
 #include <unistd.h>
 
-#include <cstdbool>
 #include <memory>
 
 #include <android-base/macros.h>
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index 54506dc..d4ba4f4 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -41,14 +41,11 @@
     defaults: ["logwrapper_common"],
 }
 
-// Build vendor logwrapper.
-// TODO: Add vendor_available to "logwrapper" module and remove "logwrapper_vendor" module
-//       when vendor_available is fully supported.
 cc_binary {
     name: "logwrapper_vendor",
+    defaults: ["logwrapper_common"],
     stem: "logwrapper",
     vendor: true,
-    defaults: ["logwrapper_common"],
 }
 
 // ========================================================
diff --git a/property_service/libpropertyinfoserializer/Android.bp b/property_service/libpropertyinfoserializer/Android.bp
index 72ae19a..3c4bdc3 100644
--- a/property_service/libpropertyinfoserializer/Android.bp
+++ b/property_service/libpropertyinfoserializer/Android.bp
@@ -35,4 +35,5 @@
         "property_info_serializer_test.cpp",
     ],
     static_libs: ["libpropertyinfoserializer"],
+    test_suites: ["device-tests"],
 }
diff --git a/rootdir/etc/public.libraries.iot.txt b/rootdir/etc/public.libraries.iot.txt
new file mode 100644
index 0000000..ff0813d
--- /dev/null
+++ b/rootdir/etc/public.libraries.iot.txt
@@ -0,0 +1,27 @@
+# See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
+libandroid.so
+libandroidthings.so
+libaaudio.so
+libc.so
+libcamera2ndk.so
+libdl.so
+libEGL.so
+libGLESv1_CM.so
+libGLESv2.so
+libGLESv3.so
+libicui18n.so
+libicuuc.so
+libjnigraphics.so
+liblog.so
+libmediandk.so
+libm.so
+libnativewindow.so
+libneuralnetworks.so
+libOpenMAXAL.so
+libOpenSLES.so
+libRS.so
+libstdc++.so
+libsync.so
+libvulkan.so
+libwebviewchromium_plat_support.so
+libz.so
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index c423c69..678b853 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -179,15 +179,41 @@
 
 toybox: acpi base64 basename blockdev cal cat chcon chgrp chmod chown
 chroot chrt cksum clear cmp comm cp cpio cut date df diff dirname dmesg
-dos2unix du echo env expand expr fallocate false file find flock free
+dos2unix du echo env expand expr fallocate false file find flock fmt free
 getenforce groups gunzip gzip head hostname hwclock id ifconfig inotifyd
-insmod ionice iorenice kill killall ln load\_policy log logname losetup
-ls lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod mkswap
-mktemp modinfo modprobe more mount mountpoint mv netstat nice nl nohup
-od paste patch pgrep pidof pkill pmap printenv printf ps pwd readlink
-realpath renice restorecon rm rmdir rmmod runcon sed sendevent seq
-setenforce setprop setsid sha1sum sha224sum sha256sum sha384sum
-sha512sum sleep sort split start stat stop strings swapoff swapon sync
-sysctl tac tail tar taskset tee time timeout top touch tr true truncate
-tty ulimit umount uname uniq unix2dos uptime usleep uudecode uuencode
-vmstat wc which whoami xargs xxd yes zcat
+insmod ionice iorenice kill killall ln load\_policy log logname losetup ls
+lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod mkswap mktemp
+modinfo modprobe more mount mountpoint mv netstat nice nl nohup od paste
+patch pgrep pidof pkill pmap printenv printf ps pwd readlink realpath
+renice restorecon rm rmdir rmmod runcon sed sendevent seq setenforce
+setprop setsid sha1sum sha224sum sha256sum sha384sum sha512sum sleep
+sort split start stat stop strings stty swapoff swapon sync sysctl tac
+tail tar taskset tee time timeout top touch tr true truncate tty ulimit
+umount uname uniq unix2dos uptime usleep uudecode uuencode vmstat wc
+which whoami xargs xxd yes zcat
+
+Android Q
+---------
+
+bzip2: bzcat bzip2 bunzip2
+
+one-true-awk: awk
+
+PCRE: egrep fgrep grep
+
+toolbox: getevent getprop newfs\_msdos
+
+toybox: acpi base64 basename blockdev cal cat chcon chgrp chmod chown
+chroot chrt cksum clear cmp comm cp cpio cut date dd df diff dirname
+dmesg dos2unix du echo env expand expr fallocate false file find flock
+fmt free getenforce groups gunzip gzip head hostname hwclock id ifconfig
+inotifyd insmod ionice iorenice kill killall ln load\_policy log logname
+losetup ls lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod
+mkswap mktemp modinfo modprobe more mount mountpoint mv nc netcat netstat
+nice nl nohup nsenter od paste patch pgrep pidof pkill pmap printenv
+printf ps pwd readlink realpath renice restorecon rm rmdir rmmod runcon
+sed sendevent seq setenforce setprop setsid sha1sum sha224sum sha256sum
+sha384sum sha512sum sleep sort split start stat stop strings stty swapoff
+swapon sync sysctl tac tail tar taskset tee time timeout top touch tr
+true truncate tty ulimit umount uname uniq unix2dos unshare uptime usleep
+uudecode uuencode vmstat wc which whoami xargs xxd yes zcat
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index ddd95b2..077f542 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -5,32 +5,8 @@
         "-Werror",
         "-Wno-unused-parameter",
         "-Wno-unused-const-variable",
-        "-include bsd-compatibility.h",
         "-D_FILE_OFFSET_BITS=64",
-    ],
-    local_include_dirs: ["upstream-netbsd/include/"],
-}
-
-cc_library_static {
-    name: "libtoolbox_dd",
-    defaults: ["toolbox_defaults"],
-    vendor_available: true,
-    srcs: [
-        "upstream-netbsd/bin/dd/args.c",
-        "upstream-netbsd/bin/dd/conv.c",
-        "upstream-netbsd/bin/dd/dd.c",
-        "upstream-netbsd/bin/dd/dd_hostops.c",
-        "upstream-netbsd/bin/dd/misc.c",
-        "upstream-netbsd/bin/dd/position.c",
-        "upstream-netbsd/lib/libc/gen/getbsize.c",
-        "upstream-netbsd/lib/libc/gen/humanize_number.c",
-        "upstream-netbsd/lib/libc/stdlib/strsuftoll.c",
-        "upstream-netbsd/lib/libc/string/swab.c",
-        "upstream-netbsd/lib/libutil/raise_default_signal.c",
-    ],
-    cflags: [
-        "-Dmain=dd_main",
-        "-DNO_CONV",
+        "-DWITHOUT_NLS",
     ],
 }
 
@@ -55,15 +31,12 @@
     generated_headers: [
         "toolbox_input_labels",
     ],
-    whole_static_libs: ["libtoolbox_dd"],
     shared_libs: [
         "libbase",
-        "libcutils",
     ],
     static_libs: ["libpropertyinfoparser"],
 
     symlinks: [
-        "dd",
         "getevent",
         "getprop",
         "newfs_msdos",
@@ -89,38 +62,9 @@
     srcs: ["r.c"],
 }
 
-// We build BSD grep separately, so it can provide egrep and fgrep too.
-cc_defaults {
-    name: "grep_common",
+cc_binary_host {
+    name: "newfs_msdos",
     defaults: ["toolbox_defaults"],
-    srcs: [
-        "upstream-netbsd/usr.bin/grep/fastgrep.c",
-        "upstream-netbsd/usr.bin/grep/file.c",
-        "upstream-netbsd/usr.bin/grep/grep.c",
-        "upstream-netbsd/usr.bin/grep/queue.c",
-        "upstream-netbsd/usr.bin/grep/util.c",
-    ],
-    symlinks: [
-        "egrep",
-        "fgrep",
-    ],
-
-    sanitize: {
-        integer_overflow: false,
-    },
-}
-
-cc_binary {
-    name: "grep",
-    defaults: ["grep_common"],
-}
-
-// Build vendor grep.
-// TODO: Add vendor_available to "grep" module and remove "grep_vendor" module
-//       when vendor_available is fully supported.
-cc_binary {
-    name: "grep_vendor",
-    stem: "grep",
-    vendor: true,
-    defaults: ["grep_common"],
+    srcs: ["newfs_msdos.c"],
+    cflags: ["-Dnewfs_msdos_main=main"]
 }
diff --git a/toolbox/bsd-compatibility.h b/toolbox/bsd-compatibility.h
deleted file mode 100644
index 7c3ddd4..0000000
--- a/toolbox/bsd-compatibility.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2014, The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdbool.h>
-#include <sys/types.h>
-
-/* We want chown to support user.group as well as user:group. */
-#define SUPPORT_DOT
-
-/* We don't localize /system/bin! */
-#define WITHOUT_NLS
-
-// NetBSD uses _DIAGASSERT to null-check arguments and the like.
-#include <assert.h>
-#define _DIAGASSERT(e) ((e) ? (void) 0 : __assert2(__FILE__, __LINE__, __func__, #e))
-
-// TODO: update our <sys/cdefs.h> to support this properly.
-#define __type_fit(t, a) (0 == 0)
-
-// TODO: should this be in our <sys/cdefs.h>?
-#define __arraycount(a) (sizeof(a) / sizeof((a)[0]))
-
-// This at least matches GNU dd(1) behavior.
-#define SIGINFO SIGUSR1
-
-#define S_ISWHT(x) false
-
-__BEGIN_DECLS
-
-/* From NetBSD <stdlib.h>. */
-#define HN_DECIMAL              0x01
-#define HN_NOSPACE              0x02
-#define HN_B                    0x04
-#define HN_DIVISOR_1000         0x08
-#define HN_GETSCALE             0x10
-#define HN_AUTOSCALE            0x20
-int	humanize_number(char *, size_t, int64_t, const char *, int, int);
-int	dehumanize_number(const char *, int64_t *);
-char	*getbsize(int *, long *);
-long long strsuftoll(const char *, const char *, long long, long long);
-long long strsuftollx(const char *, const char *, long long, long long,
-			char *, size_t);
-
-/* From NetBSD <string.h>. */
-void strmode(mode_t, char*);
-
-/* From NetBSD <sys/param.h>. */
-#define MAXBSIZE 65536
-
-/* From NetBSD <sys/stat.h>. */
-#define DEFFILEMODE (S_IRUSR | S_IWUSR)
-
-/* From NetBSD <unistd.h>. */
-void	swab(const void * __restrict, void * __restrict, ssize_t);
-
-/* From NetBSD <util.h>. */
-int		raise_default_signal(int);
-
-__END_DECLS
diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c
index d7047e2..5fc8b02 100644
--- a/toolbox/newfs_msdos.c
+++ b/toolbox/newfs_msdos.c
@@ -32,15 +32,17 @@
 
 #include <sys/param.h>
 
-#ifndef ANDROID
+#ifdef __APPLE__
+#elif defined(ANDROID)
+#include <linux/fs.h>
+#include <linux/hdreg.h>
+#include <stdarg.h>
+#include <sys/ioctl.h>
+#else
 #include <sys/fdcio.h>
 #include <sys/disk.h>
 #include <sys/disklabel.h>
 #include <sys/mount.h>
-#else
-#include <stdarg.h>
-#include <linux/fs.h>
-#include <linux/hdreg.h>
 #endif
 
 #include <sys/stat.h>
@@ -58,6 +60,10 @@
 #include <time.h>
 #include <unistd.h>
 
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
 #define MAXU16   0xffff     /* maximum unsigned 16-bit quantity */
 #define BPN      4          /* bits per nibble */
 #define NPB      2          /* nibbles per byte */
@@ -794,7 +800,10 @@
  * Get disk slice, partition, and geometry information.
  */
 
-#ifdef ANDROID
+#ifdef __APPLE__
+static void getdiskinfo(__unused int fd, __unused const char* fname, __unused const char* dtype,
+                        __unused int oflag, __unused struct bpb* bpb) {}
+#elif ANDROID
 static void getdiskinfo(int fd, const char *fname, const char *dtype,
                         __unused int oflag,struct bpb *bpb)
 {
diff --git a/toolbox/tools.h b/toolbox/tools.h
index 505f528..3d4bc3e 100644
--- a/toolbox/tools.h
+++ b/toolbox/tools.h
@@ -1,4 +1,3 @@
-TOOL(dd)
 TOOL(getevent)
 TOOL(getprop)
 TOOL(newfs_msdos)
diff --git a/toolbox/upstream-netbsd/bin/dd/args.c b/toolbox/upstream-netbsd/bin/dd/args.c
deleted file mode 100644
index 207e300..0000000
--- a/toolbox/upstream-netbsd/bin/dd/args.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*	$NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)args.c	8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dd.h"
-#include "extern.h"
-
-static int	c_arg(const void *, const void *);
-
-#ifdef NO_MSGFMT
-static void	f_msgfmt(char *) __dead;
-#else
-static void	f_msgfmt(char *);
-#endif /* NO_MSGFMT */
-
-#ifdef NO_CONV
-static void	f_conv(char *) __dead;
-#else
-static void	f_conv(char *);
-static int	c_conv(const void *, const void *);
-#endif /* NO_CONV */
-
-static void	f_bs(char *);
-static void	f_cbs(char *);
-static void	f_count(char *);
-static void	f_files(char *);
-static void	f_ibs(char *);
-static void	f_if(char *);
-static void	f_obs(char *);
-static void	f_of(char *);
-static void	f_seek(char *);
-static void	f_skip(char *);
-static void	f_progress(char *);
-
-static const struct arg {
-	const char *name;
-	void (*f)(char *);
-	u_int set, noset;
-} args[] = {
-     /* the array needs to be sorted by the first column so
-	bsearch() can be used to find commands quickly */
-	{ "bs",		f_bs,		C_BS,	 C_BS|C_IBS|C_OBS|C_OSYNC },
-	{ "cbs",	f_cbs,		C_CBS,	 C_CBS },
-	{ "conv",	f_conv,		0,	 0 },
-	{ "count",	f_count,	C_COUNT, C_COUNT },
-	{ "files",	f_files,	C_FILES, C_FILES },
-	{ "ibs",	f_ibs,		C_IBS,	 C_BS|C_IBS },
-	{ "if",		f_if,		C_IF,	 C_IF },
-	{ "iseek",	f_skip,		C_SKIP,	 C_SKIP },
-	{ "msgfmt",	f_msgfmt,	0,	 0 },
-	{ "obs",	f_obs,		C_OBS,	 C_BS|C_OBS },
-	{ "of",		f_of,		C_OF,	 C_OF },
-	{ "oseek",	f_seek,		C_SEEK,	 C_SEEK },
-	{ "progress",	f_progress,	0,	 0 },
-	{ "seek",	f_seek,		C_SEEK,	 C_SEEK },
-	{ "skip",	f_skip,		C_SKIP,	 C_SKIP },
-};
-
-/*
- * args -- parse JCL syntax of dd.
- */
-void
-jcl(char **argv)
-{
-	struct arg *ap, tmp;
-	char *oper, *arg;
-
-	in.dbsz = out.dbsz = 512;
-
-	while ((oper = *++argv) != NULL) {
-		if ((oper = strdup(oper)) == NULL) {
-			errx(EXIT_FAILURE,
-			    "unable to allocate space for the argument %s",
-			    *argv);
-			/* NOTREACHED */
-		}
-		if ((arg = strchr(oper, '=')) == NULL) {
-			errx(EXIT_FAILURE, "unknown operand %s", oper);
-			/* NOTREACHED */
-		}
-		*arg++ = '\0';
-		if (!*arg) {
-			errx(EXIT_FAILURE, "no value specified for %s", oper);
-			/* NOTREACHED */
-		}
-		tmp.name = oper;
-		if (!(ap = bsearch(&tmp, args,
-		    __arraycount(args), sizeof(*args), c_arg))) {
-			errx(EXIT_FAILURE, "unknown operand %s", tmp.name);
-			/* NOTREACHED */
-		}
-		if (ddflags & ap->noset) {
-			errx(EXIT_FAILURE,
-			    "%s: illegal argument combination or already set",
-			    tmp.name);
-			/* NOTREACHED */
-		}
-		ddflags |= ap->set;
-		ap->f(arg);
-	}
-
-	/* Final sanity checks. */
-
-	if (ddflags & C_BS) {
-		/*
-		 * Bs is turned off by any conversion -- we assume the user
-		 * just wanted to set both the input and output block sizes
-		 * and didn't want the bs semantics, so we don't warn.
-		 */
-		if (ddflags & (C_BLOCK | C_LCASE | C_SWAB | C_UCASE |
-		    C_UNBLOCK | C_OSYNC | C_ASCII | C_EBCDIC | C_SPARSE)) {
-			ddflags &= ~C_BS;
-			ddflags |= C_IBS|C_OBS;
-		}
-
-		/* Bs supersedes ibs and obs. */
-		if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
-			warnx("bs supersedes ibs and obs");
-	}
-
-	/*
-	 * Ascii/ebcdic and cbs implies block/unblock.
-	 * Block/unblock requires cbs and vice-versa.
-	 */
-	if (ddflags & (C_BLOCK|C_UNBLOCK)) {
-		if (!(ddflags & C_CBS)) {
-			errx(EXIT_FAILURE, "record operations require cbs");
-			/* NOTREACHED */
-		}
-		cfunc = ddflags & C_BLOCK ? block : unblock;
-	} else if (ddflags & C_CBS) {
-		if (ddflags & (C_ASCII|C_EBCDIC)) {
-			if (ddflags & C_ASCII) {
-				ddflags |= C_UNBLOCK;
-				cfunc = unblock;
-			} else {
-				ddflags |= C_BLOCK;
-				cfunc = block;
-			}
-		} else {
-			errx(EXIT_FAILURE,
-			    "cbs meaningless if not doing record operations");
-			/* NOTREACHED */
-		}
-	} else
-		cfunc = def;
-
-	/* Read, write and seek calls take off_t as arguments.
-	 *
-	 * The following check is not done because an off_t is a quad
-	 *  for current NetBSD implementations.
-	 *
-	 * if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
-	 *	errx(1, "seek offsets cannot be larger than %d", INT_MAX);
-	 */
-}
-
-static int
-c_arg(const void *a, const void *b)
-{
-
-	return (strcmp(((const struct arg *)a)->name,
-	    ((const struct arg *)b)->name));
-}
-
-static void
-f_bs(char *arg)
-{
-
-	in.dbsz = out.dbsz = strsuftoll("block size", arg, 1, UINT_MAX);
-}
-
-static void
-f_cbs(char *arg)
-{
-
-	cbsz = strsuftoll("conversion record size", arg, 1, UINT_MAX);
-}
-
-static void
-f_count(char *arg)
-{
-
-	cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
-	if (!cpy_cnt)
-		terminate(0);
-}
-
-static void
-f_files(char *arg)
-{
-
-	files_cnt = (u_int)strsuftoll("file count", arg, 0, UINT_MAX);
-	if (!files_cnt)
-		terminate(0);
-}
-
-static void
-f_ibs(char *arg)
-{
-
-	if (!(ddflags & C_BS))
-		in.dbsz = strsuftoll("input block size", arg, 1, UINT_MAX);
-}
-
-static void
-f_if(char *arg)
-{
-
-	in.name = arg;
-}
-
-#ifdef NO_MSGFMT
-/* Build a small version (i.e. for a ramdisk root) */
-static void
-f_msgfmt(char *arg)
-{
-
-	errx(EXIT_FAILURE, "msgfmt option disabled");
-	/* NOTREACHED */
-}
-#else	/* NO_MSGFMT */
-static void
-f_msgfmt(char *arg)
-{
-
-	/*
-	 * If the format string is not valid, dd_write_msg() will print
-	 * an error and exit.
-	 */
-	dd_write_msg(arg, 0);
-
-	msgfmt = arg;
-}
-#endif	/* NO_MSGFMT */
-
-static void
-f_obs(char *arg)
-{
-
-	if (!(ddflags & C_BS))
-		out.dbsz = strsuftoll("output block size", arg, 1, UINT_MAX);
-}
-
-static void
-f_of(char *arg)
-{
-
-	out.name = arg;
-}
-
-static void
-f_seek(char *arg)
-{
-
-	out.offset = strsuftoll("seek blocks", arg, 0, LLONG_MAX);
-}
-
-static void
-f_skip(char *arg)
-{
-
-	in.offset = strsuftoll("skip blocks", arg, 0, LLONG_MAX);
-}
-
-static void
-f_progress(char *arg)
-{
-
-	progress = strsuftoll("progress blocks", arg, 0, LLONG_MAX);
-}
-
-#ifdef	NO_CONV
-/* Build a small version (i.e. for a ramdisk root) */
-static void
-f_conv(char *arg)
-{
-
-	errx(EXIT_FAILURE, "conv option disabled");
-	/* NOTREACHED */
-}
-#else	/* NO_CONV */
-
-static const struct conv {
-	const char *name;
-	u_int set, noset;
-	const u_char *ctab;
-} clist[] = {
-	{ "ascii",	C_ASCII,	C_EBCDIC,	e2a_POSIX },
-	{ "block",	C_BLOCK,	C_UNBLOCK,	NULL },
-	{ "ebcdic",	C_EBCDIC,	C_ASCII,	a2e_POSIX },
-	{ "ibm",	C_EBCDIC,	C_ASCII,	a2ibm_POSIX },
-	{ "lcase",	C_LCASE,	C_UCASE,	NULL },
-	{ "noerror",	C_NOERROR,	0,		NULL },
-	{ "notrunc",	C_NOTRUNC,	0,		NULL },
-	{ "oldascii",	C_ASCII,	C_EBCDIC,	e2a_32V },
-	{ "oldebcdic",	C_EBCDIC,	C_ASCII,	a2e_32V },
-	{ "oldibm",	C_EBCDIC,	C_ASCII,	a2ibm_32V },
-	{ "osync",	C_OSYNC,	C_BS,		NULL },
-	{ "sparse",	C_SPARSE,	0,		NULL },
-	{ "swab",	C_SWAB,		0,		NULL },
-	{ "sync",	C_SYNC,		0,		NULL },
-	{ "ucase",	C_UCASE,	C_LCASE,	NULL },
-	{ "unblock",	C_UNBLOCK,	C_BLOCK,	NULL },
-	/* If you add items to this table, be sure to add the
-	 * conversions to the C_BS check in the jcl routine above.
-	 */
-};
-
-static void
-f_conv(char *arg)
-{
-	struct conv *cp, tmp;
-
-	while (arg != NULL) {
-		tmp.name = strsep(&arg, ",");
-		if (!(cp = bsearch(&tmp, clist,
-		    __arraycount(clist), sizeof(*clist), c_conv))) {
-			errx(EXIT_FAILURE, "unknown conversion %s", tmp.name);
-			/* NOTREACHED */
-		}
-		if (ddflags & cp->noset) {
-			errx(EXIT_FAILURE,
-			    "%s: illegal conversion combination", tmp.name);
-			/* NOTREACHED */
-		}
-		ddflags |= cp->set;
-		if (cp->ctab)
-			ctab = cp->ctab;
-	}
-}
-
-static int
-c_conv(const void *a, const void *b)
-{
-
-	return (strcmp(((const struct conv *)a)->name,
-	    ((const struct conv *)b)->name));
-}
-
-#endif	/* NO_CONV */
diff --git a/toolbox/upstream-netbsd/bin/dd/conv.c b/toolbox/upstream-netbsd/bin/dd/conv.c
deleted file mode 100644
index d4a8a09..0000000
--- a/toolbox/upstream-netbsd/bin/dd/conv.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*	$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)conv.c	8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "dd.h"
-#include "extern.h"
-
-/*
- * def --
- * Copy input to output.  Input is buffered until reaches obs, and then
- * output until less than obs remains.  Only a single buffer is used.
- * Worst case buffer calculation is (ibs + obs - 1).
- */
-void
-def(void)
-{
-	uint64_t cnt;
-	u_char *inp;
-	const u_char *t;
-
-	if ((t = ctab) != NULL)
-		for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
-			*inp = t[*inp];
-
-	/* Make the output buffer look right. */
-	out.dbp = in.dbp;
-	out.dbcnt = in.dbcnt;
-
-	if (in.dbcnt >= out.dbsz) {
-		/* If the output buffer is full, write it. */
-		dd_out(0);
-
-		/*
-		 * Ddout copies the leftover output to the beginning of
-		 * the buffer and resets the output buffer.  Reset the
-		 * input buffer to match it.
-	 	 */
-		in.dbp = out.dbp;
-		in.dbcnt = out.dbcnt;
-	}
-}
-
-void
-def_close(void)
-{
-
-	/* Just update the count, everything is already in the buffer. */
-	if (in.dbcnt)
-		out.dbcnt = in.dbcnt;
-}
-
-#ifdef	NO_CONV
-/* Build a smaller version (i.e. for a miniroot) */
-/* These can not be called, but just in case...  */
-static const char no_block[] = "unblock and -DNO_CONV?";
-void block(void)		{ errx(EXIT_FAILURE, "%s", no_block + 2); }
-void block_close(void)		{ errx(EXIT_FAILURE, "%s", no_block + 2); }
-void unblock(void)		{ errx(EXIT_FAILURE, "%s", no_block); }
-void unblock_close(void)	{ errx(EXIT_FAILURE, "%s", no_block); }
-#else	/* NO_CONV */
-
-/*
- * Copy variable length newline terminated records with a max size cbsz
- * bytes to output.  Records less than cbs are padded with spaces.
- *
- * max in buffer:  MAX(ibs, cbsz)
- * max out buffer: obs + cbsz
- */
-void
-block(void)
-{
-	static int intrunc;
-	int ch = 0;	/* pacify gcc */
-	uint64_t cnt, maxlen;
-	u_char *inp, *outp;
-	const u_char *t;
-
-	/*
-	 * Record truncation can cross block boundaries.  If currently in a
-	 * truncation state, keep tossing characters until reach a newline.
-	 * Start at the beginning of the buffer, as the input buffer is always
-	 * left empty.
-	 */
-	if (intrunc) {
-		for (inp = in.db, cnt = in.dbrcnt;
-		    cnt && *inp++ != '\n'; --cnt);
-		if (!cnt) {
-			in.dbcnt = 0;
-			in.dbp = in.db;
-			return;
-		}
-		intrunc = 0;
-		/* Adjust the input buffer numbers. */
-		in.dbcnt = cnt - 1;
-		in.dbp = inp + cnt - 1;
-	}
-
-	/*
-	 * Copy records (max cbsz size chunks) into the output buffer.  The
-	 * translation is done as we copy into the output buffer.
-	 */
-	for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
-		maxlen = MIN(cbsz, in.dbcnt);
-		if ((t = ctab) != NULL)
-			for (cnt = 0;
-			    cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
-				*outp++ = t[ch];
-		else
-			for (cnt = 0;
-			    cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
-				*outp++ = ch;
-		/*
-		 * Check for short record without a newline.  Reassemble the
-		 * input block.
-		 */
-		if (ch != '\n' && in.dbcnt < cbsz) {
-			(void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
-			break;
-		}
-
-		/* Adjust the input buffer numbers. */
-		in.dbcnt -= cnt;
-		if (ch == '\n')
-			--in.dbcnt;
-
-		/* Pad short records with spaces. */
-		if (cnt < cbsz)
-			(void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
-		else {
-			/*
-			 * If the next character wouldn't have ended the
-			 * block, it's a truncation.
-			 */
-			if (!in.dbcnt || *inp != '\n')
-				++st.trunc;
-
-			/* Toss characters to a newline. */
-			for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt);
-			if (!in.dbcnt)
-				intrunc = 1;
-			else
-				--in.dbcnt;
-		}
-
-		/* Adjust output buffer numbers. */
-		out.dbp += cbsz;
-		if ((out.dbcnt += cbsz) >= out.dbsz)
-			dd_out(0);
-		outp = out.dbp;
-	}
-	in.dbp = in.db + in.dbcnt;
-}
-
-void
-block_close(void)
-{
-
-	/*
-	 * Copy any remaining data into the output buffer and pad to a record.
-	 * Don't worry about truncation or translation, the input buffer is
-	 * always empty when truncating, and no characters have been added for
-	 * translation.  The bottom line is that anything left in the input
-	 * buffer is a truncated record.  Anything left in the output buffer
-	 * just wasn't big enough.
-	 */
-	if (in.dbcnt) {
-		++st.trunc;
-		(void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
-		(void)memset(out.dbp + in.dbcnt,
-		    ctab ? ctab[' '] : ' ', cbsz - in.dbcnt);
-		out.dbcnt += cbsz;
-	}
-}
-
-/*
- * Convert fixed length (cbsz) records to variable length.  Deletes any
- * trailing blanks and appends a newline.
- *
- * max in buffer:  MAX(ibs, cbsz) + cbsz
- * max out buffer: obs + cbsz
- */
-void
-unblock(void)
-{
-	uint64_t cnt;
-	u_char *inp;
-	const u_char *t;
-
-	/* Translation and case conversion. */
-	if ((t = ctab) != NULL)
-		for (cnt = in.dbrcnt, inp = in.dbp - 1; cnt--; inp--)
-			*inp = t[*inp];
-	/*
-	 * Copy records (max cbsz size chunks) into the output buffer.  The
-	 * translation has to already be done or we might not recognize the
-	 * spaces.
-	 */
-	for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
-		for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t);
-		if (t >= inp) {
-			cnt = t - inp + 1;
-			(void)memmove(out.dbp, inp, cnt);
-			out.dbp += cnt;
-			out.dbcnt += cnt;
-		}
-		++out.dbcnt;
-		*out.dbp++ = '\n';
-		if (out.dbcnt >= out.dbsz)
-			dd_out(0);
-	}
-	if (in.dbcnt)
-		(void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
-	in.dbp = in.db + in.dbcnt;
-}
-
-void
-unblock_close(void)
-{
-	uint64_t cnt;
-	u_char *t;
-
-	if (in.dbcnt) {
-		warnx("%s: short input record", in.name);
-		for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t);
-		if (t >= in.db) {
-			cnt = t - in.db + 1;
-			(void)memmove(out.dbp, in.db, cnt);
-			out.dbp += cnt;
-			out.dbcnt += cnt;
-		}
-		++out.dbcnt;
-		*out.dbp++ = '\n';
-	}
-}
-
-#endif	/* NO_CONV */
diff --git a/toolbox/upstream-netbsd/bin/dd/dd.c b/toolbox/upstream-netbsd/bin/dd/dd.c
deleted file mode 100644
index 03d080c..0000000
--- a/toolbox/upstream-netbsd/bin/dd/dd.c
+++ /dev/null
@@ -1,598 +0,0 @@
-/*	$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\
- The Regents of the University of California.  All rights reserved.");
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)dd.c	8.5 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/mtio.h>
-#include <sys/time.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <locale.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "dd.h"
-#include "extern.h"
-
-static void dd_close(void);
-static void dd_in(void);
-static void getfdtype(IO *);
-static void redup_clean_fd(IO *);
-static void setup(void);
-
-int main(int, char *[]);
-
-IO		in, out;		/* input/output state */
-STAT		st;			/* statistics */
-void		(*cfunc)(void);		/* conversion function */
-uint64_t	cpy_cnt;		/* # of blocks to copy */
-static off_t	pending = 0;		/* pending seek if sparse */
-u_int		ddflags;		/* conversion options */
-uint64_t	cbsz;			/* conversion block size */
-u_int		files_cnt = 1;		/* # of files to copy */
-uint64_t	progress = 0;		/* display sign of life */
-const u_char	*ctab;			/* conversion table */
-sigset_t	infoset;		/* a set blocking SIGINFO */
-const char	*msgfmt = "posix";	/* default summary() message format */
-
-/*
- * Ops for stdin/stdout and crunch'd dd.  These are always host ops.
- */
-static const struct ddfops ddfops_stdfd = {
-	.op_open = open,
-	.op_close = close,
-	.op_fcntl = fcntl,
-	.op_ioctl = ioctl,
-	.op_fstat = fstat,
-	.op_fsync = fsync,
-	.op_ftruncate = ftruncate,
-	.op_lseek = lseek,
-	.op_read = read,
-	.op_write = write,
-};
-extern const struct ddfops ddfops_prog;
-
-int
-main(int argc, char *argv[])
-{
-	int ch;
-
-	setprogname(argv[0]);
-	(void)setlocale(LC_ALL, "");
-
-	while ((ch = getopt(argc, argv, "")) != -1) {
-		switch (ch) {
-		default:
-			errx(EXIT_FAILURE, "usage: dd [operand ...]");
-			/* NOTREACHED */
-		}
-	}
-	argc -= (optind - 1);
-	argv += (optind - 1);
-
-	jcl(argv);
-#ifndef CRUNCHOPS
-	if (ddfops_prog.op_init && ddfops_prog.op_init() == -1)
-		err(1, "prog init");
-#endif
-	setup();
-
-	(void)signal(SIGINFO, summaryx);
-	(void)signal(SIGINT, terminate);
-	(void)sigemptyset(&infoset);
-	(void)sigaddset(&infoset, SIGINFO);
-
-	(void)atexit(summary);
-
-	while (files_cnt--)
-		dd_in();
-
-	dd_close();
-	exit(0);
-	/* NOTREACHED */
-}
-
-static void
-setup(void)
-{
-#ifdef CRUNCHOPS
-	const struct ddfops *prog_ops = &ddfops_stdfd;
-#else
-	const struct ddfops *prog_ops = &ddfops_prog;
-#endif
-
-	if (in.name == NULL) {
-		in.name = "stdin";
-		in.fd = STDIN_FILENO;
-		in.ops = &ddfops_stdfd;
-	} else {
-		in.ops = prog_ops;
-		in.fd = ddop_open(in, in.name, O_RDONLY, 0);
-		if (in.fd < 0)
-			err(EXIT_FAILURE, "%s", in.name);
-			/* NOTREACHED */
-
-		/* Ensure in.fd is outside the stdio descriptor range */
-		redup_clean_fd(&in);
-	}
-
-	getfdtype(&in);
-
-	if (files_cnt > 1 && !(in.flags & ISTAPE)) {
-		errx(EXIT_FAILURE, "files is not supported for non-tape devices");
-		/* NOTREACHED */
-	}
-
-	if (out.name == NULL) {
-		/* No way to check for read access here. */
-		out.fd = STDOUT_FILENO;
-		out.name = "stdout";
-		out.ops = &ddfops_stdfd;
-	} else {
-		out.ops = prog_ops;
-#define	OFLAGS \
-    (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
-		out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE);
-		/*
-		 * May not have read access, so try again with write only.
-		 * Without read we may have a problem if output also does
-		 * not support seeks.
-		 */
-		if (out.fd < 0) {
-			out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS,
-			    DEFFILEMODE);
-			out.flags |= NOREAD;
-		}
-		if (out.fd < 0) {
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-		}
-
-		/* Ensure out.fd is outside the stdio descriptor range */
-		redup_clean_fd(&out);
-	}
-
-	getfdtype(&out);
-
-	/*
-	 * Allocate space for the input and output buffers.  If not doing
-	 * record oriented I/O, only need a single buffer.
-	 */
-	if (!(ddflags & (C_BLOCK|C_UNBLOCK))) {
-		size_t dbsz = out.dbsz;
-		if (!(ddflags & C_BS))
-			dbsz += in.dbsz - 1;
-		if ((in.db = malloc(dbsz)) == NULL) {
-			err(EXIT_FAILURE, NULL);
-			/* NOTREACHED */
-		}
-		out.db = in.db;
-	} else if ((in.db =
-	    malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL ||
-	    (out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) {
-		err(EXIT_FAILURE, NULL);
-		/* NOTREACHED */
-	}
-	in.dbp = in.db;
-	out.dbp = out.db;
-
-	/* Position the input/output streams. */
-	if (in.offset)
-		pos_in();
-	if (out.offset)
-		pos_out();
-
-	/*
-	 * Truncate the output file; ignore errors because it fails on some
-	 * kinds of output files, tapes, for example.
-	 */
-	if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK))
-		(void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz);
-
-	/*
-	 * If converting case at the same time as another conversion, build a
-	 * table that does both at once.  If just converting case, use the
-	 * built-in tables.
-	 */
-	if (ddflags & (C_LCASE|C_UCASE)) {
-#ifdef	NO_CONV
-		/* Should not get here, but just in case... */
-		errx(EXIT_FAILURE, "case conv and -DNO_CONV");
-		/* NOTREACHED */
-#else	/* NO_CONV */
-		u_int cnt;
-
-		if (ddflags & C_ASCII || ddflags & C_EBCDIC) {
-			if (ddflags & C_LCASE) {
-				for (cnt = 0; cnt < 256; ++cnt)
-					casetab[cnt] = tolower(ctab[cnt]);
-			} else {
-				for (cnt = 0; cnt < 256; ++cnt)
-					casetab[cnt] = toupper(ctab[cnt]);
-			}
-		} else {
-			if (ddflags & C_LCASE) {
-				for (cnt = 0; cnt < 256; ++cnt)
-					casetab[cnt] = tolower(cnt);
-			} else {
-				for (cnt = 0; cnt < 256; ++cnt)
-					casetab[cnt] = toupper(cnt);
-			}
-		}
-
-		ctab = casetab;
-#endif	/* NO_CONV */
-	}
-
-	(void)gettimeofday(&st.start, NULL);	/* Statistics timestamp. */
-}
-
-static void
-getfdtype(IO *io)
-{
-	struct mtget mt;
-	struct stat sb;
-
-	if (io->ops->op_fstat(io->fd, &sb)) {
-		err(EXIT_FAILURE, "%s", io->name);
-		/* NOTREACHED */
-	}
-	if (S_ISCHR(sb.st_mode))
-		io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt)
-		    ? ISCHR : ISTAPE;
-	else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1
-	    && errno == ESPIPE)
-		io->flags |= ISPIPE;		/* XXX fixed in 4.4BSD */
-}
-
-/*
- * Move the parameter file descriptor to a descriptor that is outside the
- * stdio descriptor range, if necessary.  This is required to avoid
- * accidentally outputting completion or error messages into the
- * output file that were intended for the tty.
- */
-static void
-redup_clean_fd(IO *io)
-{
-	int fd = io->fd;
-	int newfd;
-
-	if (fd != STDIN_FILENO && fd != STDOUT_FILENO &&
-	    fd != STDERR_FILENO)
-		/* File descriptor is ok, return immediately. */
-		return;
-
-	/*
-	 * 3 is the first descriptor greater than STD*_FILENO.  Any
-	 * free descriptor valued 3 or above is acceptable...
-	 */
-	newfd = io->ops->op_fcntl(fd, F_DUPFD, 3);
-	if (newfd < 0) {
-		err(EXIT_FAILURE, "dupfd IO");
-		/* NOTREACHED */
-	}
-
-	io->ops->op_close(fd);
-	io->fd = newfd;
-}
-
-static void
-dd_in(void)
-{
-	int flags;
-	int64_t n;
-
-	for (flags = ddflags;;) {
-		if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt)
-			return;
-
-		/*
-		 * Clear the buffer first if doing "sync" on input.
-		 * If doing block operations use spaces.  This will
-		 * affect not only the C_NOERROR case, but also the
-		 * last partial input block which should be padded
-		 * with zero and not garbage.
-		 */
-		if (flags & C_SYNC) {
-			if (flags & (C_BLOCK|C_UNBLOCK))
-				(void)memset(in.dbp, ' ', in.dbsz);
-			else
-				(void)memset(in.dbp, 0, in.dbsz);
-		}
-
-		n = ddop_read(in, in.fd, in.dbp, in.dbsz);
-		if (n == 0) {
-			in.dbrcnt = 0;
-			return;
-		}
-
-		/* Read error. */
-		if (n < 0) {
-
-			/*
-			 * If noerror not specified, die.  POSIX requires that
-			 * the warning message be followed by an I/O display.
-			 */
-			if (!(flags & C_NOERROR)) {
-				err(EXIT_FAILURE, "%s", in.name);
-				/* NOTREACHED */
-			}
-			warn("%s", in.name);
-			summary();
-
-			/*
-			 * If it's not a tape drive or a pipe, seek past the
-			 * error.  If your OS doesn't do the right thing for
-			 * raw disks this section should be modified to re-read
-			 * in sector size chunks.
-			 */
-			if (!(in.flags & (ISPIPE|ISTAPE)) &&
-			    ddop_lseek(in, in.fd, (off_t)in.dbsz, SEEK_CUR))
-				warn("%s", in.name);
-
-			/* If sync not specified, omit block and continue. */
-			if (!(ddflags & C_SYNC))
-				continue;
-
-			/* Read errors count as full blocks. */
-			in.dbcnt += in.dbrcnt = in.dbsz;
-			++st.in_full;
-
-		/* Handle full input blocks. */
-		} else if ((uint64_t)n == in.dbsz) {
-			in.dbcnt += in.dbrcnt = n;
-			++st.in_full;
-
-		/* Handle partial input blocks. */
-		} else {
-			/* If sync, use the entire block. */
-			if (ddflags & C_SYNC)
-				in.dbcnt += in.dbrcnt = in.dbsz;
-			else
-				in.dbcnt += in.dbrcnt = n;
-			++st.in_part;
-		}
-
-		/*
-		 * POSIX states that if bs is set and no other conversions
-		 * than noerror, notrunc or sync are specified, the block
-		 * is output without buffering as it is read.
-		 */
-		if (ddflags & C_BS) {
-			out.dbcnt = in.dbcnt;
-			dd_out(1);
-			in.dbcnt = 0;
-			continue;
-		}
-
-		if (ddflags & C_SWAB) {
-			if ((n = in.dbrcnt) & 1) {
-				++st.swab;
-				--n;
-			}
-			swab(in.dbp, in.dbp, n);
-		}
-
-		in.dbp += in.dbrcnt;
-		(*cfunc)();
-	}
-}
-
-/*
- * Cleanup any remaining I/O and flush output.  If necessary, output file
- * is truncated.
- */
-static void
-dd_close(void)
-{
-
-	if (cfunc == def)
-		def_close();
-	else if (cfunc == block)
-		block_close();
-	else if (cfunc == unblock)
-		unblock_close();
-	if (ddflags & C_OSYNC && out.dbcnt < out.dbsz) {
-		(void)memset(out.dbp, 0, out.dbsz - out.dbcnt);
-		out.dbcnt = out.dbsz;
-	}
-	/* If there are pending sparse blocks, make sure
-	 * to write out the final block un-sparse
-	 */
-	if ((out.dbcnt == 0) && pending) {
-		memset(out.db, 0, out.dbsz);
-		out.dbcnt = out.dbsz;
-		out.dbp = out.db + out.dbcnt;
-		pending -= out.dbsz;
-	}
-	if (out.dbcnt)
-		dd_out(1);
-
-	/*
-	 * Reporting nfs write error may be deferred until next
-	 * write(2) or close(2) system call.  So, we need to do an
-	 * extra check.  If an output is stdout, the file structure
-	 * may be shared with other processes and close(2) just
-	 * decreases the reference count.
-	 */
-	if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1
-	    && errno != EINVAL) {
-		err(EXIT_FAILURE, "fsync stdout");
-		/* NOTREACHED */
-	}
-	if (ddop_close(out, out.fd) == -1) {
-		err(EXIT_FAILURE, "close");
-		/* NOTREACHED */
-	}
-}
-
-void
-dd_out(int force)
-{
-	static int warned;
-	int64_t cnt, n, nw;
-	u_char *outp;
-
-	/*
-	 * Write one or more blocks out.  The common case is writing a full
-	 * output block in a single write; increment the full block stats.
-	 * Otherwise, we're into partial block writes.  If a partial write,
-	 * and it's a character device, just warn.  If a tape device, quit.
-	 *
-	 * The partial writes represent two cases.  1: Where the input block
-	 * was less than expected so the output block was less than expected.
-	 * 2: Where the input block was the right size but we were forced to
-	 * write the block in multiple chunks.  The original versions of dd(1)
-	 * never wrote a block in more than a single write, so the latter case
-	 * never happened.
-	 *
-	 * One special case is if we're forced to do the write -- in that case
-	 * we play games with the buffer size, and it's usually a partial write.
-	 */
-	outp = out.db;
-	for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
-		for (cnt = n;; cnt -= nw) {
-
-			if (!force && ddflags & C_SPARSE) {
-				int sparse, i;
-				sparse = 1;	/* Is buffer sparse? */
-				for (i = 0; i < cnt; i++)
-					if (outp[i] != 0) {
-						sparse = 0;
-						break;
-					}
-				if (sparse) {
-					pending += cnt;
-					outp += cnt;
-					nw = 0;
-					break;
-				}
-			}
-			if (pending != 0) {
-				if (ddop_lseek(out,
-				    out.fd, pending, SEEK_CUR) == -1)
-					err(EXIT_FAILURE, "%s: seek error creating sparse file",
-					    out.name);
-			}
-			nw = bwrite(&out, outp, cnt);
-			if (nw <= 0) {
-				if (nw == 0)
-					errx(EXIT_FAILURE,
-						"%s: end of device", out.name);
-					/* NOTREACHED */
-				if (errno != EINTR)
-					err(EXIT_FAILURE, "%s", out.name);
-					/* NOTREACHED */
-				nw = 0;
-			}
-			if (pending) {
-				st.bytes += pending;
-				st.sparse += pending/out.dbsz;
-				st.out_full += pending/out.dbsz;
-				pending = 0;
-			}
-			outp += nw;
-			st.bytes += nw;
-			if (nw == n) {
-				if ((uint64_t)n != out.dbsz)
-					++st.out_part;
-				else
-					++st.out_full;
-				break;
-			}
-			++st.out_part;
-			if (nw == cnt)
-				break;
-			if (out.flags & ISCHR && !warned) {
-				warned = 1;
-				warnx("%s: short write on character device", out.name);
-			}
-			if (out.flags & ISTAPE)
-				errx(EXIT_FAILURE,
-					"%s: short write on tape device", out.name);
-				/* NOTREACHED */
-
-		}
-		if ((out.dbcnt -= n) < out.dbsz)
-			break;
-	}
-
-	/* Reassemble the output block. */
-	if (out.dbcnt)
-		(void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
-	out.dbp = out.db + out.dbcnt;
-
-	if (progress && (st.out_full + st.out_part) % progress == 0)
-		(void)write(STDERR_FILENO, ".", 1);
-}
-
-/*
- * A protected against SIGINFO write
- */
-ssize_t
-bwrite(IO *io, const void *buf, size_t len)
-{
-	sigset_t oset;
-	ssize_t rv;
-	int oerrno;
-
-	(void)sigprocmask(SIG_BLOCK, &infoset, &oset);
-	rv = io->ops->op_write(io->fd, buf, len);
-	oerrno = errno;
-	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
-	errno = oerrno;
-	return (rv);
-}
diff --git a/toolbox/upstream-netbsd/bin/dd/dd.h b/toolbox/upstream-netbsd/bin/dd/dd.h
deleted file mode 100644
index b01c7b3..0000000
--- a/toolbox/upstream-netbsd/bin/dd/dd.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*	$NetBSD: dd.h,v 1.15 2011/02/04 19:42:12 pooka Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)dd.h	8.3 (Berkeley) 4/2/94
- */
-
-#include <sys/stat.h>
-
-struct ddfops {
-	int (*op_init)(void);
-
-	int (*op_open)(const char *, int, ...);
-	int (*op_close)(int);
-
-	int (*op_fcntl)(int, int, ...);
-#ifdef __ANDROID__
-	int (*op_ioctl)(int, int, ...);
-#else
-	int (*op_ioctl)(int, unsigned long, ...);
-#endif
-
-	int (*op_fstat)(int, struct stat *);
-	int (*op_fsync)(int);
-	int (*op_ftruncate)(int, off_t);
-
-	off_t (*op_lseek)(int, off_t, int);
-
-	ssize_t (*op_read)(int, void *, size_t);
-	ssize_t (*op_write)(int, const void *, size_t);
-};
-
-#define ddop_open(dir, a1, a2, ...)	dir.ops->op_open(a1, a2, __VA_ARGS__)
-#define ddop_close(dir, a1)		dir.ops->op_close(a1)
-#define ddop_fcntl(dir, a1, a2, ...)	dir.ops->op_fcntl(a1, a2, __VA_ARGS__)
-#define ddop_ioctl(dir, a1, a2, ...)	dir.ops->op_ioctl(a1, a2, __VA_ARGS__)
-#define ddop_fsync(dir, a1)		dir.ops->op_fsync(a1)
-#define ddop_ftruncate(dir, a1, a2)	dir.ops->op_ftruncate(a1, a2)
-#define ddop_lseek(dir, a1, a2, a3)	dir.ops->op_lseek(a1, a2, a3)
-#define ddop_read(dir, a1, a2, a3)	dir.ops->op_read(a1, a2, a3)
-#define ddop_write(dir, a1, a2, a3)	dir.ops->op_write(a1, a2, a3)
-
-/* Input/output stream state. */
-typedef struct {
-	u_char		*db;		/* buffer address */
-	u_char		*dbp;		/* current buffer I/O address */
-	uint64_t	dbcnt;		/* current buffer byte count */
-	int64_t		dbrcnt;		/* last read byte count */
-	uint64_t	dbsz;		/* buffer size */
-
-#define	ISCHR		0x01		/* character device (warn on short) */
-#define	ISPIPE		0x02		/* pipe (not truncatable) */
-#define	ISTAPE		0x04		/* tape (not seekable) */
-#define	NOREAD		0x08		/* not readable */
-	u_int		flags;
-
-	const char  	*name;		/* name */
-	int		fd;		/* file descriptor */
-	uint64_t	offset;		/* # of blocks to skip */
-	struct ddfops	const *ops;	/* ops to use with fd */
-} IO;
-
-typedef struct {
-	uint64_t	in_full;	/* # of full input blocks */
-	uint64_t	in_part;	/* # of partial input blocks */
-	uint64_t	out_full;	/* # of full output blocks */
-	uint64_t	out_part;	/* # of partial output blocks */
-	uint64_t	trunc;		/* # of truncated records */
-	uint64_t	swab;		/* # of odd-length swab blocks */
-	uint64_t	sparse;		/* # of sparse output blocks */
-	uint64_t	bytes;		/* # of bytes written */
-	struct timeval	start;		/* start time of dd */
-} STAT;
-
-/* Flags (in ddflags). */
-#define	C_ASCII		0x00001
-#define	C_BLOCK		0x00002
-#define	C_BS		0x00004
-#define	C_CBS		0x00008
-#define	C_COUNT		0x00010
-#define	C_EBCDIC	0x00020
-#define	C_FILES		0x00040
-#define	C_IBS		0x00080
-#define	C_IF		0x00100
-#define	C_LCASE		0x00200
-#define	C_NOERROR	0x00400
-#define	C_NOTRUNC	0x00800
-#define	C_OBS		0x01000
-#define	C_OF		0x02000
-#define	C_SEEK		0x04000
-#define	C_SKIP		0x08000
-#define	C_SWAB		0x10000
-#define	C_SYNC		0x20000
-#define	C_UCASE		0x40000
-#define	C_UNBLOCK	0x80000
-#define	C_OSYNC		0x100000
-#define	C_SPARSE	0x200000
diff --git a/toolbox/upstream-netbsd/bin/dd/dd_hostops.c b/toolbox/upstream-netbsd/bin/dd/dd_hostops.c
deleted file mode 100644
index d6e7a89..0000000
--- a/toolbox/upstream-netbsd/bin/dd/dd_hostops.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*      $NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $	*/
-
-/*-
- * Copyright (c) 2010 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-__RCSID("$NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
-#endif /* !lint */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "dd.h"
-
-const struct ddfops ddfops_prog = {
-	.op_open = open,
-	.op_close = close,
-	.op_fcntl = fcntl,
-	.op_ioctl = ioctl,
-	.op_fstat = fstat,
-	.op_fsync = fsync,
-	.op_ftruncate = ftruncate,
-	.op_lseek = lseek,
-	.op_read = read,
-	.op_write = write,
-};
diff --git a/toolbox/upstream-netbsd/bin/dd/extern.h b/toolbox/upstream-netbsd/bin/dd/extern.h
deleted file mode 100644
index 9c59021..0000000
--- a/toolbox/upstream-netbsd/bin/dd/extern.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*	$NetBSD: extern.h,v 1.22 2011/11/07 22:24:23 jym Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)extern.h	8.3 (Berkeley) 4/2/94
- */
-
-#include <sys/cdefs.h>
-
-#ifdef NO_CONV
-__dead void block(void);
-__dead void block_close(void);
-__dead void unblock(void);
-__dead void unblock_close(void);
-#else
-void block(void);
-void block_close(void);
-void unblock(void);
-void unblock_close(void);
-#endif
-
-#ifndef NO_MSGFMT
-int dd_write_msg(const char *, int);
-#endif
-
-void dd_out(int);
-void def(void);
-void def_close(void);
-void jcl(char **);
-void pos_in(void);
-void pos_out(void);
-void summary(void);
-void summaryx(int);
-__dead void terminate(int);
-void unblock(void);
-void unblock_close(void);
-ssize_t bwrite(IO *, const void *, size_t);
-
-extern IO		in, out;
-extern STAT		st;
-extern void		(*cfunc)(void);
-extern uint64_t		cpy_cnt;
-extern uint64_t		cbsz;
-extern u_int		ddflags;
-extern u_int		files_cnt;
-extern uint64_t		progress;
-extern const u_char	*ctab;
-extern const u_char	a2e_32V[], a2e_POSIX[];
-extern const u_char	e2a_32V[], e2a_POSIX[];
-extern const u_char	a2ibm_32V[], a2ibm_POSIX[];
-extern u_char		casetab[];
-extern const char	*msgfmt;
diff --git a/toolbox/upstream-netbsd/bin/dd/misc.c b/toolbox/upstream-netbsd/bin/dd/misc.c
deleted file mode 100644
index 0fac98b..0000000
--- a/toolbox/upstream-netbsd/bin/dd/misc.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*	$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)misc.c	8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <util.h>
-#include <inttypes.h>
-
-#include "dd.h"
-#include "extern.h"
-
-#define	tv2mS(tv) ((tv).tv_sec * 1000LL + ((tv).tv_usec + 500) / 1000)
-
-static void posix_summary(void);
-#ifndef NO_MSGFMT
-static void custom_summary(void);
-static void human_summary(void);
-static void quiet_summary(void);
-
-static void buffer_write(const char *, size_t, int);
-#endif /* NO_MSGFMT */
-
-void
-summary(void)
-{
-
-	if (progress)
-		(void)write(STDERR_FILENO, "\n", 1);
-
-#ifdef NO_MSGFMT
-	return posix_summary();
-#else /* NO_MSGFMT */
-	if (strncmp(msgfmt, "human", sizeof("human")) == 0)
-		return human_summary();
-
-	if (strncmp(msgfmt, "posix", sizeof("posix")) == 0)
-		return posix_summary();
-
-	if (strncmp(msgfmt, "quiet", sizeof("quiet")) == 0)
-		return quiet_summary();
-
-	return custom_summary();
-#endif /* NO_MSGFMT */
-}
-
-static void
-posix_summary(void)
-{
-	char buf[100];
-	int64_t mS;
-	struct timeval tv;
-
-	if (progress)
-		(void)write(STDERR_FILENO, "\n", 1);
-
-	(void)gettimeofday(&tv, NULL);
-	mS = tv2mS(tv) - tv2mS(st.start);
-	if (mS == 0)
-		mS = 1;
-
-	/* Use snprintf(3) so that we don't reenter stdio(3). */
-	(void)snprintf(buf, sizeof(buf),
-	    "%llu+%llu records in\n%llu+%llu records out\n",
-	    (unsigned long long)st.in_full,  (unsigned long long)st.in_part,
-	    (unsigned long long)st.out_full, (unsigned long long)st.out_part);
-	(void)write(STDERR_FILENO, buf, strlen(buf));
-	if (st.swab) {
-		(void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n",
-		    (unsigned long long)st.swab,
-		    (st.swab == 1) ? "block" : "blocks");
-		(void)write(STDERR_FILENO, buf, strlen(buf));
-	}
-	if (st.trunc) {
-		(void)snprintf(buf, sizeof(buf), "%llu truncated %s\n",
-		    (unsigned long long)st.trunc,
-		    (st.trunc == 1) ? "block" : "blocks");
-		(void)write(STDERR_FILENO, buf, strlen(buf));
-	}
-	if (st.sparse) {
-		(void)snprintf(buf, sizeof(buf), "%llu sparse output %s\n",
-		    (unsigned long long)st.sparse,
-		    (st.sparse == 1) ? "block" : "blocks");
-		(void)write(STDERR_FILENO, buf, strlen(buf));
-	}
-	(void)snprintf(buf, sizeof(buf),
-	    "%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n",
-	    (unsigned long long) st.bytes,
-	    (long) (mS / 1000),
-	    (int) (mS % 1000),
-	    (unsigned long long) (st.bytes * 1000LL / mS));
-	(void)write(STDERR_FILENO, buf, strlen(buf));
-}
-
-/* ARGSUSED */
-void
-summaryx(int notused)
-{
-
-	summary();
-}
-
-/* ARGSUSED */
-void
-terminate(int signo)
-{
-
-	summary();
-	(void)raise_default_signal(signo);
-	_exit(127);
-}
-
-#ifndef NO_MSGFMT
-/*
- * Buffer write(2) calls
- */
-static void
-buffer_write(const char *str, size_t size, int flush)
-{
-	static char wbuf[128];
-	static size_t cnt = 0; /* Internal counter to allow wbuf to wrap */
-	
-	unsigned int i;
-
-	for (i = 0; i < size; i++) {
-		if (str != NULL) {
-			wbuf[cnt++] = str[i];
-		}
-		if (cnt >= sizeof(wbuf)) {
-			(void)write(STDERR_FILENO, wbuf, cnt);
-			cnt = 0;
-		}
-	}
-
-	if (flush != 0) {
-		(void)write(STDERR_FILENO, wbuf, cnt);
-		cnt = 0;
-	}
-}
-
-/*
- * Write summary to stderr according to format 'fmt'. If 'enable' is 0, it
- * will not attempt to write anything. Can be used to validate the
- * correctness of the 'fmt' string.
- */
-int
-dd_write_msg(const char *fmt, int enable)
-{
-	char hbuf[7], nbuf[32];
-	const char *ptr;
-	int64_t mS;
-	struct timeval tv;
-
-	(void)gettimeofday(&tv, NULL);
-	mS = tv2mS(tv) - tv2mS(st.start);
-	if (mS == 0)
-		mS = 1;
-
-#define ADDC(c) do { if (enable != 0) buffer_write(&c, 1, 0); } \
-	while (/*CONSTCOND*/0)
-#define ADDS(p) do { if (enable != 0) buffer_write(p, strlen(p), 0); } \
-	while (/*CONSTCOND*/0)
-
-	for (ptr = fmt; *ptr; ptr++) {
-		if (*ptr != '%') {
-			ADDC(*ptr);
-			continue;
-		}
-
- 		switch (*++ptr) {
-		case 'b':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.bytes);
-			ADDS(nbuf);
-			break;
-		case 'B':
-			if (humanize_number(hbuf, sizeof(hbuf),
-			    st.bytes, "B",
-			    HN_AUTOSCALE, HN_DECIMAL) == -1)
-				warnx("humanize_number (bytes transferred)");
-			ADDS(hbuf);
-			break;
-		case 'e':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long) (st.bytes * 1000LL / mS));
-			ADDS(nbuf);
-			break;
-		case 'E':
-			if (humanize_number(hbuf, sizeof(hbuf),
-			    st.bytes * 1000LL / mS, "B",
-			    HN_AUTOSCALE, HN_DECIMAL) == -1)
-				warnx("humanize_number (bytes per second)");
-			ADDS(hbuf); ADDS("/sec");
-			break;
-		case 'i':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.in_part);
-			ADDS(nbuf);
-			break;
-		case 'I':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.in_full);
-			ADDS(nbuf);
-			break;
-		case 'o':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.out_part);
-			ADDS(nbuf);
-			break;
-		case 'O':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.out_full);
-			ADDS(nbuf);
-			break;
-		case 's':
-			(void)snprintf(nbuf, sizeof(nbuf), "%li.%03d",
-			    (long) (mS / 1000), (int) (mS % 1000));
-			ADDS(nbuf);
-			break;
-		case 'p':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.sparse);
-			ADDS(nbuf);
-			break;
-		case 't':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.trunc);
-			ADDS(nbuf);
-			break;
-		case 'w':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.swab);
-			ADDS(nbuf);
-			break;
-		case 'P':
-			ADDS("block");
-			if (st.sparse != 1) ADDS("s");
-			break;
-		case 'T':
-			ADDS("block");
-			if (st.trunc != 1) ADDS("s");
-			break;
-		case 'W':
-			ADDS("block");
-			if (st.swab != 1) ADDS("s");
-			break;
-		case '%':
-			ADDC(*ptr);
-			break;
-		default:
-			if (*ptr == '\0')
-				goto done;
-			errx(EXIT_FAILURE, "unknown specifier '%c' in "
-			    "msgfmt string", *ptr);
-			/* NOTREACHED */
-		}
-	}
-
-done:
-	/* flush buffer */
-	buffer_write(NULL, 0, 1);
-	return 0;
-}
-
-static void
-custom_summary(void)
-{
-
-	dd_write_msg(msgfmt, 1);
-}
-
-static void
-human_summary(void)
-{
-	(void)dd_write_msg("%I+%i records in\n%O+%o records out\n", 1);
-	if (st.swab) {
-		(void)dd_write_msg("%w odd length swab %W\n", 1);
-	}
-	if (st.trunc) {
-		(void)dd_write_msg("%t truncated %T\n", 1);
-	}
-	if (st.sparse) {
-		(void)dd_write_msg("%p sparse output %P\n", 1);
-	}
-	(void)dd_write_msg("%b bytes (%B) transferred in %s secs "
-	    "(%e bytes/sec - %E)\n", 1);
-}
-
-static void
-quiet_summary(void)
-{
-
-	/* stay quiet */
-}
-#endif /* NO_MSGFMT */
diff --git a/toolbox/upstream-netbsd/bin/dd/position.c b/toolbox/upstream-netbsd/bin/dd/position.c
deleted file mode 100644
index 36dd580..0000000
--- a/toolbox/upstream-netbsd/bin/dd/position.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*	$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)position.c	8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/mtio.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "dd.h"
-#include "extern.h"
-
-/*
- * Position input/output data streams before starting the copy.  Device type
- * dependent.  Seekable devices use lseek, and the rest position by reading.
- * Seeking past the end of file can cause null blocks to be written to the
- * output.
- */
-void
-pos_in(void)
-{
-	int bcnt, cnt, nr, warned;
-
-	/* If not a pipe or tape device, try to seek on it. */
-	if (!(in.flags & (ISPIPE|ISTAPE))) {
-		if (ddop_lseek(in, in.fd,
-		    (off_t)in.offset * (off_t)in.dbsz, SEEK_CUR) == -1) {
-			err(EXIT_FAILURE, "%s", in.name);
-			/* NOTREACHED */
-		}
-		return;
-		/* NOTREACHED */
-	}
-
-	/*
-	 * Read the data.  If a pipe, read until satisfy the number of bytes
-	 * being skipped.  No differentiation for reading complete and partial
-	 * blocks for other devices.
-	 */
-	for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
-		if ((nr = ddop_read(in, in.fd, in.db, bcnt)) > 0) {
-			if (in.flags & ISPIPE) {
-				if (!(bcnt -= nr)) {
-					bcnt = in.dbsz;
-					--cnt;
-				}
-			} else
-				--cnt;
-			continue;
-		}
-
-		if (nr == 0) {
-			if (files_cnt > 1) {
-				--files_cnt;
-				continue;
-			}
-			errx(EXIT_FAILURE, "skip reached end of input");
-			/* NOTREACHED */
-		}
-
-		/*
-		 * Input error -- either EOF with no more files, or I/O error.
-		 * If noerror not set die.  POSIX requires that the warning
-		 * message be followed by an I/O display.
-		 */
-		if (ddflags & C_NOERROR) {
-			if (!warned) {
-
-				warn("%s", in.name);
-				warned = 1;
-				summary();
-			}
-			continue;
-		}
-		err(EXIT_FAILURE, "%s", in.name);
-		/* NOTREACHED */
-	}
-}
-
-void
-pos_out(void)
-{
-	struct mtop t_op;
-	int n;
-	uint64_t cnt;
-
-	/*
-	 * If not a tape, try seeking on the file.  Seeking on a pipe is
-	 * going to fail, but don't protect the user -- they shouldn't
-	 * have specified the seek operand.
-	 */
-	if (!(out.flags & ISTAPE)) {
-		if (ddop_lseek(out, out.fd,
-		    (off_t)out.offset * (off_t)out.dbsz, SEEK_SET) == -1)
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-		return;
-	}
-
-	/* If no read access, try using mtio. */
-	if (out.flags & NOREAD) {
-		t_op.mt_op = MTFSR;
-		t_op.mt_count = out.offset;
-
-		if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) < 0)
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-		return;
-	}
-
-	/* Read it. */
-	for (cnt = 0; cnt < out.offset; ++cnt) {
-		if ((n = ddop_read(out, out.fd, out.db, out.dbsz)) > 0)
-			continue;
-
-		if (n < 0)
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-
-		/*
-		 * If reach EOF, fill with NUL characters; first, back up over
-		 * the EOF mark.  Note, cnt has not yet been incremented, so
-		 * the EOF read does not count as a seek'd block.
-		 */
-		t_op.mt_op = MTBSR;
-		t_op.mt_count = 1;
-		if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) == -1)
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-
-		while (cnt++ < out.offset)
-			if ((uint64_t)(n = bwrite(&out,
-			    out.db, out.dbsz)) != out.dbsz)
-				err(EXIT_FAILURE, "%s", out.name);
-				/* NOTREACHED */
-		break;
-	}
-}
diff --git a/toolbox/upstream-netbsd/include/namespace.h b/toolbox/upstream-netbsd/include/namespace.h
deleted file mode 100644
index e69de29..0000000
--- a/toolbox/upstream-netbsd/include/namespace.h
+++ /dev/null
diff --git a/toolbox/upstream-netbsd/include/sys/extattr.h b/toolbox/upstream-netbsd/include/sys/extattr.h
deleted file mode 100644
index e69de29..0000000
--- a/toolbox/upstream-netbsd/include/sys/extattr.h
+++ /dev/null
diff --git a/toolbox/upstream-netbsd/include/util.h b/toolbox/upstream-netbsd/include/util.h
deleted file mode 100644
index e69de29..0000000
--- a/toolbox/upstream-netbsd/include/util.h
+++ /dev/null
diff --git a/toolbox/upstream-netbsd/lib/libc/gen/getbsize.c b/toolbox/upstream-netbsd/lib/libc/gen/getbsize.c
deleted file mode 100644
index a9ce2c1..0000000
--- a/toolbox/upstream-netbsd/lib/libc/gen/getbsize.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*	$NetBSD: getbsize.c,v 1.17 2012/06/25 22:32:43 abs Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)getbsize.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: getbsize.c,v 1.17 2012/06/25 22:32:43 abs Exp $");
-#endif
-#endif /* not lint */
-
-#include "namespace.h"
-
-#include <assert.h>
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef __weak_alias
-__weak_alias(getbsize,_getbsize)
-#endif
-
-char *
-getbsize(int *headerlenp, long *blocksizep)
-{
-	static char header[20];
-	long n, max, mul, blocksize;
-	char *ep, *p;
-	const char *form;
-
-#define	KB	(1024L)
-#define	MB	(1024L * 1024L)
-#define	GB	(1024L * 1024L * 1024L)
-#define	MAXB	GB		/* No tera, peta, nor exa. */
-	form = "";
-	if ((p = getenv("BLOCKSIZE")) != NULL && *p != '\0') {
-		if ((n = strtol(p, &ep, 10)) < 0)
-			goto underflow;
-		if (n == 0)
-			n = 1;
-		if (*ep && ep[1])
-			goto fmterr;
-		switch (*ep) {
-		case 'G': case 'g':
-			form = "G";
-			max = MAXB / GB;
-			mul = GB;
-			break;
-		case 'K': case 'k':
-			form = "K";
-			max = MAXB / KB;
-			mul = KB;
-			break;
-		case 'M': case 'm':
-			form = "M";
-			max = MAXB / MB;
-			mul = MB;
-			break;
-		case '\0':
-			max = MAXB;
-			mul = 1;
-			break;
-		default:
-fmterr:			warnx("%s: unknown blocksize", p);
-			n = 512;
-			mul = 1;
-			max = 0;
-			break;
-		}
-		if (n > max) {
-			warnx("maximum blocksize is %ldG", MAXB / GB);
-			n = max;
-		}
-		if ((blocksize = n * mul) < 512) {
-underflow:		warnx("%s: minimum blocksize is 512", p);
-			form = "";
-			blocksize = n = 512;
-		}
-	} else
-		blocksize = n = 512;
-
-	if (headerlenp)
-		*headerlenp =
-		    snprintf(header, sizeof(header), "%ld%s-blocks", n, form);
-	if (blocksizep)
-		*blocksizep = blocksize;
-	return (header);
-}
diff --git a/toolbox/upstream-netbsd/lib/libc/gen/humanize_number.c b/toolbox/upstream-netbsd/lib/libc/gen/humanize_number.c
deleted file mode 100644
index 533560f..0000000
--- a/toolbox/upstream-netbsd/lib/libc/gen/humanize_number.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*	$NetBSD: humanize_number.c,v 1.16 2012/03/17 20:01:14 christos Exp $	*/
-
-/*
- * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
- * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: humanize_number.c,v 1.16 2012/03/17 20:01:14 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include "namespace.h"
-#include <assert.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <locale.h>
-
-int
-humanize_number(char *buf, size_t len, int64_t bytes,
-    const char *suffix, int scale, int flags)
-{
-	const char *prefixes, *sep;
-	int	b, r, s1, s2, sign;
-	int64_t	divisor, max, post = 1;
-	size_t	i, baselen, maxscale;
-
-	_DIAGASSERT(buf != NULL);
-	_DIAGASSERT(suffix != NULL);
-	_DIAGASSERT(scale >= 0);
-
-	if (flags & HN_DIVISOR_1000) {
-		/* SI for decimal multiplies */
-		divisor = 1000;
-		if (flags & HN_B)
-			prefixes = "B\0k\0M\0G\0T\0P\0E";
-		else
-			prefixes = "\0\0k\0M\0G\0T\0P\0E";
-	} else {
-		/*
-		 * binary multiplies
-		 * XXX IEC 60027-2 recommends Ki, Mi, Gi...
-		 */
-		divisor = 1024;
-		if (flags & HN_B)
-			prefixes = "B\0K\0M\0G\0T\0P\0E";
-		else
-			prefixes = "\0\0K\0M\0G\0T\0P\0E";
-	}
-
-#define	SCALE2PREFIX(scale)	(&prefixes[(scale) << 1])
-	maxscale = 7;
-
-	if ((size_t)scale >= maxscale &&
-	    (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
-		return (-1);
-
-	if (buf == NULL || suffix == NULL)
-		return (-1);
-
-	if (len > 0)
-		buf[0] = '\0';
-	if (bytes < 0) {
-		sign = -1;
-		baselen = 3;		/* sign, digit, prefix */
-		if (-bytes < INT64_MAX / 100)
-			bytes *= -100;
-		else {
-			bytes = -bytes;
-			post = 100;
-			baselen += 2;
-		}
-	} else {
-		sign = 1;
-		baselen = 2;		/* digit, prefix */
-		if (bytes < INT64_MAX / 100)
-			bytes *= 100;
-		else {
-			post = 100;
-			baselen += 2;
-		}
-	}
-	if (flags & HN_NOSPACE)
-		sep = "";
-	else {
-		sep = " ";
-		baselen++;
-	}
-	baselen += strlen(suffix);
-
-	/* Check if enough room for `x y' + suffix + `\0' */
-	if (len < baselen + 1)
-		return (-1);
-
-	if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
-		/* See if there is additional columns can be used. */
-		for (max = 100, i = len - baselen; i-- > 0;)
-			max *= 10;
-
-		/*
-		 * Divide the number until it fits the given column.
-		 * If there will be an overflow by the rounding below,
-		 * divide once more.
-		 */
-		for (i = 0; bytes >= max - 50 && i < maxscale; i++)
-			bytes /= divisor;
-
-		if (scale & HN_GETSCALE) {
-			_DIAGASSERT(__type_fit(int, i));
-			return (int)i;
-		}
-	} else
-		for (i = 0; i < (size_t)scale && i < maxscale; i++)
-			bytes /= divisor;
-	bytes *= post;
-
-	/* If a value <= 9.9 after rounding and ... */
-	if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
-		/* baselen + \0 + .N */
-		if (len < baselen + 1 + 2)
-			return (-1);
-		b = ((int)bytes + 5) / 10;
-		s1 = b / 10;
-		s2 = b % 10;
-		r = snprintf(buf, len, "%d%s%d%s%s%s",
-		    sign * s1, localeconv()->decimal_point, s2,
-		    sep, SCALE2PREFIX(i), suffix);
-	} else
-		r = snprintf(buf, len, "%" PRId64 "%s%s%s",
-		    sign * ((bytes + 50) / 100),
-		    sep, SCALE2PREFIX(i), suffix);
-
-	return (r);
-}
diff --git a/toolbox/upstream-netbsd/lib/libc/stdlib/strsuftoll.c b/toolbox/upstream-netbsd/lib/libc/stdlib/strsuftoll.c
deleted file mode 100644
index 80fc52f..0000000
--- a/toolbox/upstream-netbsd/lib/libc/stdlib/strsuftoll.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*	$NetBSD: strsuftoll.c,v 1.9 2011/10/22 22:08:47 christos Exp $	*/
-/*-
- * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Luke Mewburn.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: strsuftoll.c,v 1.9 2011/10/22 22:08:47 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#ifdef _LIBC
-#include "namespace.h"
-#endif
-
-#if !HAVE_STRSUFTOLL
-
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef _LIBC
-# ifdef __weak_alias
-__weak_alias(strsuftoll, _strsuftoll)
-__weak_alias(strsuftollx, _strsuftollx)
-# endif
-#endif /* LIBC */
-
-/*
- * Convert an expression of the following forms to a (u)int64_t.
- * 	1) A positive decimal number.
- *	2) A positive decimal number followed by a b (mult by 512).
- *	3) A positive decimal number followed by a k (mult by 1024).
- *	4) A positive decimal number followed by a m (mult by 1048576).
- *	5) A positive decimal number followed by a g (mult by 1073741824).
- *	6) A positive decimal number followed by a t (mult by 1099511627776).
- *	7) A positive decimal number followed by a w (mult by sizeof int)
- *	8) Two or more positive decimal numbers (with/without k,b or w).
- *	   separated by x (also * for backwards compatibility), specifying
- *	   the product of the indicated values.
- * Returns the result upon successful conversion, or exits with an
- * appropriate error.
- * 
- */
-/* LONGLONG */
-long long
-strsuftoll(const char *desc, const char *val,
-    long long min, long long max)
-{
-	long long result;
-	char	errbuf[100];
-
-	result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
-	if (*errbuf != '\0')
-		errx(EXIT_FAILURE, "%s", errbuf);
-	return result;
-}
-
-/*
- * As strsuftoll(), but returns the error message into the provided buffer
- * rather than exiting with it.
- */
-/* LONGLONG */
-static long long
-__strsuftollx(const char *desc, const char *val,
-    long long min, long long max, char *ebuf, size_t ebuflen, size_t depth)
-{
-	long long num, t;
-	char	*expr;
-
-	_DIAGASSERT(desc != NULL);
-	_DIAGASSERT(val != NULL);
-	_DIAGASSERT(ebuf != NULL);
-
-	if (depth > 16) {
-		snprintf(ebuf, ebuflen, "%s: Recursion limit exceeded", desc);
-		return 0;
-	}
-
-	while (isspace((unsigned char)*val))	/* Skip leading space */
-		val++;
-
-	errno = 0;
-	num = strtoll(val, &expr, 10);
-	if (errno == ERANGE)
-		goto erange;			/* Overflow */
-
-	if (expr == val)			/* No digits */
-		goto badnum;
-
-	switch (*expr) {
-	case 'b':
-		t = num;
-		num *= 512;			/* 1 block */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 'k':
-		t = num;
-		num *= 1024;			/* 1 kibibyte */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 'm':
-		t = num;
-		num *= 1048576;			/* 1 mebibyte */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 'g':
-		t = num;
-		num *= 1073741824;		/* 1 gibibyte */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 't':
-		t = num;
-		num *= 1099511627776LL;		/* 1 tebibyte */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 'w':
-		t = num;
-		num *= sizeof(int);		/* 1 word */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	}
-
-	switch (*expr) {
-	case '\0':
-		break;
-	case '*':				/* Backward compatible */
-	case 'x':
-		t = num;
-		num *= __strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen,
-			depth + 1);
-		if (*ebuf != '\0')
-			return 0;
-		if (t > num) {
- erange:	 	
-			errno = ERANGE;
-			snprintf(ebuf, ebuflen, "%s: %s", desc, strerror(errno));
-			return 0;
-		}
-		break;
-	default:
- badnum:
-		snprintf(ebuf, ebuflen, "%s `%s': illegal number", desc, val);
-		return 0;
-	}
-	if (num < min) {
-		/* LONGLONG */
-		snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
-		    desc, (long long)num, (long long)min);
-		return 0;
-	}
-	if (num > max) {
-		/* LONGLONG */
-		snprintf(ebuf, ebuflen, "%s %lld is greater than %lld.",
-		    desc, (long long)num, (long long)max);
-		return 0;
-	}
-	*ebuf = '\0';
-	return num;
-}
-
-long long
-strsuftollx(const char *desc, const char *val,
-    long long min, long long max, char *ebuf, size_t ebuflen)
-{
-	return __strsuftollx(desc, val, min, max, ebuf, ebuflen, 0);
-}
-#endif /* !HAVE_STRSUFTOLL */
diff --git a/toolbox/upstream-netbsd/lib/libc/string/swab.c b/toolbox/upstream-netbsd/lib/libc/string/swab.c
deleted file mode 100644
index 392b186..0000000
--- a/toolbox/upstream-netbsd/lib/libc/string/swab.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*	$NetBSD: swab.c,v 1.18 2011/01/04 17:14:07 martin Exp $	*/
-
-/*
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jeffrey Mogul.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)swab.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: swab.c,v 1.18 2011/01/04 17:14:07 martin Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#include <unistd.h>
-
-void
-swab(const void * __restrict from, void * __restrict to, ssize_t len)
-{
-	char temp;
-	const char *fp;
-	char *tp;
-
-	if (len <= 1)
-		return;
-
-	_DIAGASSERT(from != NULL);
-	_DIAGASSERT(to != NULL);
-
-	len /= 2;
-	fp = (const char *)from;
-	tp = (char *)to;
-#define	STEP	temp = *fp++,*tp++ = *fp++,*tp++ = temp
-
-	if (__predict_false(len == 1)) {
-		STEP;
-		return;
-	}
-
-	/* round to multiple of 8 */
-	while ((--len % 8) != 0)
-		STEP;
-	len /= 8;
-	if (len == 0)
-		return;
-	while (len-- != 0) {
-		STEP; STEP; STEP; STEP;
-		STEP; STEP; STEP; STEP;
-	}
-}
diff --git a/toolbox/upstream-netbsd/lib/libutil/raise_default_signal.c b/toolbox/upstream-netbsd/lib/libutil/raise_default_signal.c
deleted file mode 100644
index 50cffd4..0000000
--- a/toolbox/upstream-netbsd/lib/libutil/raise_default_signal.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*	$NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $	 */
-
-/*-
- * Copyright (c) 2007 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Luke Mewburn.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $");
-#endif
-
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <util.h>
-
-#if ! HAVE_RAISE_DEFAULT_SIGNAL
-/*
- * raise_default_signal sig
- *	Raise the default signal handler for sig, by
- *	- block all signals
- *	- set the signal handler to SIG_DFL
- *	- raise the signal
- *	- unblock the signal to deliver it
- *
- *	The original signal mask and signal handler is restored on exit
- *	(whether successful or not).
- *
- *	Returns 0 on success, or -1 on failure with errno set to
- *	on of the values for sigemptyset(), sigaddset(), sigprocmask(),
- *	sigaction(), or raise().
- */
-int
-raise_default_signal(int sig)
-{
-	struct sigaction origact, act;
-	sigset_t origmask, fullmask, mask;
-	int retval, oerrno;
-
-	retval = -1;
-
-		/* Setup data structures */
-		/* XXX memset(3) isn't async-safe according to signal(7) */
-	(void)memset(&act, 0, sizeof(act));
-	act.sa_handler = SIG_DFL;
-	act.sa_flags = 0;
-	if ((sigemptyset(&act.sa_mask) == -1) ||
-	    (sigfillset(&fullmask) == -1) ||
-	    (sigemptyset(&mask) == -1) ||
-	    (sigaddset(&mask, sig) == -1))
-		goto restore_none;
-
-		/* Block all signals */
-	if (sigprocmask(SIG_BLOCK, &fullmask, &origmask) == -1)
-		goto restore_none;
-		/* (use 'goto restore_mask' to restore state) */
-
-		/* Enable the SIG_DFL handler */
-	if (sigaction(sig, &act, &origact) == -1)
-		goto restore_mask;
-		/* (use 'goto restore_act' to restore state) */
-
-		/* Raise the signal, and unblock the signal to deliver it */
-	if ((raise(sig) == -1) ||
-	    (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1))
-		goto restore_act;
-
-		/* Flag successful raise() */
-	retval = 0;
-
-		/* Restore the original handler */
- restore_act:
-	oerrno = errno;
-	(void)sigaction(sig, &origact, NULL);
-	errno = oerrno;
-
-		/* Restore the original mask */
- restore_mask:
-	oerrno = errno;
-	(void)sigprocmask(SIG_SETMASK, &origmask, NULL);
-	errno = oerrno;
-
- restore_none:
-	return retval;
-}
-
-#endif	/* ! HAVE_RAISE_DEFAULT_SIGNAL */
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c b/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c
deleted file mode 100644
index 2fcd864..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*	$OpenBSD: util.c,v 1.36 2007/10/02 17:59:18 otto Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/fastgrep.c 211496 2010-08-19 09:28:59Z des $ */
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * XXX: This file is a speed up for grep to cover the defects of the
- * regex library.  These optimizations should practically be implemented
- * there keeping this code clean.  This is a future TODO, but for the
- * meantime, we need to use this workaround.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: fastgrep.c,v 1.5 2011/04/18 03:27:40 joerg Exp $");
-
-#include <limits.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "grep.h"
-
-static inline int	grep_cmp(const unsigned char *, const unsigned char *, size_t);
-static inline void	grep_revstr(unsigned char *, int);
-
-void
-fgrepcomp(fastgrep_t *fg, const char *pat)
-{
-	unsigned int i;
-
-	/* Initialize. */
-	fg->len = strlen(pat);
-	fg->bol = false;
-	fg->eol = false;
-	fg->reversed = false;
-
-	fg->pattern = (unsigned char *)grep_strdup(pat);
-
-	/* Preprocess pattern. */
-	for (i = 0; i <= UCHAR_MAX; i++)
-		fg->qsBc[i] = fg->len;
-	for (i = 1; i < fg->len; i++)
-		fg->qsBc[fg->pattern[i]] = fg->len - i;
-}
-
-/*
- * Returns: -1 on failure, 0 on success
- */
-int
-fastcomp(fastgrep_t *fg, const char *pat)
-{
-	unsigned int i;
-	int firstHalfDot = -1;
-	int firstLastHalfDot = -1;
-	int hasDot = 0;
-	int lastHalfDot = 0;
-	int shiftPatternLen;
-
-	/* Initialize. */
-	fg->len = strlen(pat);
-	fg->bol = false;
-	fg->eol = false;
-	fg->reversed = false;
-	fg->word = wflag;
-
-	/* Remove end-of-line character ('$'). */
-	if (fg->len > 0 && pat[fg->len - 1] == '$') {
-		fg->eol = true;
-		fg->len--;
-	}
-
-	/* Remove beginning-of-line character ('^'). */
-	if (pat[0] == '^') {
-		fg->bol = true;
-		fg->len--;
-		pat++;
-	}
-
-	if (fg->len >= 14 &&
-	    memcmp(pat, "[[:<:]]", 7) == 0 &&
-	    memcmp(pat + fg->len - 7, "[[:>:]]", 7) == 0) {
-		fg->len -= 14;
-		pat += 7;
-		/* Word boundary is handled separately in util.c */
-		fg->word = true;
-	}
-
-	/*
-	 * pat has been adjusted earlier to not include '^', '$' or
-	 * the word match character classes at the beginning and ending
-	 * of the string respectively.
-	 */
-	fg->pattern = grep_malloc(fg->len + 1);
-	memcpy(fg->pattern, pat, fg->len);
-	fg->pattern[fg->len] = '\0';
-
-	/* Look for ways to cheat...er...avoid the full regex engine. */
-	for (i = 0; i < fg->len; i++) {
-		/* Can still cheat? */
-		if (fg->pattern[i] == '.') {
-			hasDot = i;
-			if (i < fg->len / 2) {
-				if (firstHalfDot < 0)
-					/* Closest dot to the beginning */
-					firstHalfDot = i;
-			} else {
-				/* Closest dot to the end of the pattern. */
-				lastHalfDot = i;
-				if (firstLastHalfDot < 0)
-					firstLastHalfDot = i;
-			}
-		} else {
-			/* Free memory and let others know this is empty. */
-			free(fg->pattern);
-			fg->pattern = NULL;
-			return (-1);
-		}
-	}
-
-	/*
-	 * Determine if a reverse search would be faster based on the placement
-	 * of the dots.
-	 */
-	if ((!(lflag || cflag)) && ((!(fg->bol || fg->eol)) &&
-	    ((lastHalfDot) && ((firstHalfDot < 0) ||
-	    ((fg->len - (lastHalfDot + 1)) < (size_t)firstHalfDot)))) &&
-	    !oflag && !color) {
-		fg->reversed = true;
-		hasDot = fg->len - (firstHalfDot < 0 ?
-		    firstLastHalfDot : firstHalfDot) - 1;
-		grep_revstr(fg->pattern, fg->len);
-	}
-
-	/*
-	 * Normal Quick Search would require a shift based on the position the
-	 * next character after the comparison is within the pattern.  With
-	 * wildcards, the position of the last dot effects the maximum shift
-	 * distance.
-	 * The closer to the end the wild card is the slower the search.  A
-	 * reverse version of this algorithm would be useful for wildcards near
-	 * the end of the string.
-	 *
-	 * Examples:
-	 * Pattern	Max shift
-	 * -------	---------
-	 * this		5
-	 * .his		4
-	 * t.is		3
-	 * th.s		2
-	 * thi.		1
-	 */
-
-	/* Adjust the shift based on location of the last dot ('.'). */
-	shiftPatternLen = fg->len - hasDot;
-
-	/* Preprocess pattern. */
-	for (i = 0; i <= (signed)UCHAR_MAX; i++)
-		fg->qsBc[i] = shiftPatternLen;
-	for (i = hasDot + 1; i < fg->len; i++) {
-		fg->qsBc[fg->pattern[i]] = fg->len - i;
-	}
-
-	/*
-	 * Put pattern back to normal after pre-processing to allow for easy
-	 * comparisons later.
-	 */
-	if (fg->reversed)
-		grep_revstr(fg->pattern, fg->len);
-
-	return (0);
-}
-
-int
-grep_search(fastgrep_t *fg, const unsigned char *data, size_t len, regmatch_t *pmatch)
-{
-	unsigned int j;
-	int ret = REG_NOMATCH;
-
-	if (pmatch->rm_so == (ssize_t)len)
-		return (ret);
-
-	if (fg->bol && pmatch->rm_so != 0) {
-		pmatch->rm_so = len;
-		pmatch->rm_eo = len;
-		return (ret);
-	}
-
-	/* No point in going farther if we do not have enough data. */
-	if (len < fg->len)
-		return (ret);
-
-	/* Only try once at the beginning or ending of the line. */
-	if (fg->bol || fg->eol) {
-		/* Simple text comparison. */
-		/* Verify data is >= pattern length before searching on it. */
-		if (len >= fg->len) {
-			/* Determine where in data to start search at. */
-			j = fg->eol ? len - fg->len : 0;
-			if (!((fg->bol && fg->eol) && (len != fg->len)))
-				if (grep_cmp(fg->pattern, data + j,
-				    fg->len) == -1) {
-					pmatch->rm_so = j;
-					pmatch->rm_eo = j + fg->len;
-						ret = 0;
-				}
-		}
-	} else if (fg->reversed) {
-		/* Quick Search algorithm. */
-		j = len;
-		do {
-			if (grep_cmp(fg->pattern, data + j - fg->len,
-				fg->len) == -1) {
-				pmatch->rm_so = j - fg->len;
-				pmatch->rm_eo = j;
-				ret = 0;
-				break;
-			}
-			/* Shift if within bounds, otherwise, we are done. */
-			if (j == fg->len)
-				break;
-			j -= fg->qsBc[data[j - fg->len - 1]];
-		} while (j >= fg->len);
-	} else {
-		/* Quick Search algorithm. */
-		j = pmatch->rm_so;
-		do {
-			if (grep_cmp(fg->pattern, data + j, fg->len) == -1) {
-				pmatch->rm_so = j;
-				pmatch->rm_eo = j + fg->len;
-				ret = 0;
-				break;
-			}
-
-			/* Shift if within bounds, otherwise, we are done. */
-			if (j + fg->len == len)
-				break;
-			else
-				j += fg->qsBc[data[j + fg->len]];
-		} while (j <= (len - fg->len));
-	}
-
-	return (ret);
-}
-
-/*
- * Returns:	i >= 0 on failure (position that it failed)
- *		-1 on success
- */
-static inline int
-grep_cmp(const unsigned char *pat, const unsigned char *data, size_t len)
-{
-	size_t size;
-	wchar_t *wdata, *wpat;
-	unsigned int i;
-
-	if (iflag) {
-		if ((size = mbstowcs(NULL, (const char *)data, 0)) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		wdata = grep_malloc(size * sizeof(wint_t));
-
-		if (mbstowcs(wdata, (const char *)data, size) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		if ((size = mbstowcs(NULL, (const char *)pat, 0)) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		wpat = grep_malloc(size * sizeof(wint_t));
-
-		if (mbstowcs(wpat, (const char *)pat, size) == ((size_t) - 1))
-			return (-1);
-		for (i = 0; i < len; i++) {
-			if ((towlower(wpat[i]) == towlower(wdata[i])) ||
-			    ((grepbehave != GREP_FIXED) && wpat[i] == L'.'))
-				continue;
-			free(wpat);
-			free(wdata);
-				return (i);
-		}
-	} else {
-		for (i = 0; i < len; i++) {
-			if ((pat[i] == data[i]) || ((grepbehave != GREP_FIXED) &&
-			    pat[i] == '.'))
-				continue;
-			return (i);
-		}
-	}
-	return (-1);
-}
-
-static inline void
-grep_revstr(unsigned char *str, int len)
-{
-	int i;
-	char c;
-
-	for (i = 0; i < len / 2; i++) {
-		c = str[i];
-		str[i] = str[len - i - 1];
-		str[len - i - 1] = c;
-	}
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/file.c b/toolbox/upstream-netbsd/usr.bin/grep/file.c
deleted file mode 100644
index cf4a0fa..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/file.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*	$NetBSD: file.c,v 1.7 2011/04/18 22:46:48 joerg Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/file.c 211496 2010-08-19 09:28:59Z des $	*/
-/*	$OpenBSD: file.c,v 1.11 2010/07/02 20:48:48 nicm Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
- * Copyright (C) 2010 Dimitry Andric <dimitry@andric.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: file.c,v 1.7 2011/04/18 22:46:48 joerg Exp $");
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifndef __ANDROID__
-#include <bzlib.h>
-#endif
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <wchar.h>
-#include <wctype.h>
-#ifndef __ANDROID__
-#include <zlib.h>
-#endif
-
-#include "grep.h"
-
-#define	MAXBUFSIZ	(32 * 1024)
-#define	LNBUFBUMP	80
-
-#ifndef __ANDROID__
-static gzFile gzbufdesc;
-static BZFILE* bzbufdesc;
-#endif
-
-static unsigned char buffer[MAXBUFSIZ];
-static unsigned char *bufpos;
-static size_t bufrem;
-
-static unsigned char *lnbuf;
-static size_t lnbuflen;
-
-static inline int
-grep_refill(struct file *f)
-{
-	ssize_t nr;
-#ifndef __ANDROID__
-	int bzerr;
-#endif
-
-	bufpos = buffer;
-	bufrem = 0;
-
-#ifndef __ANDROID__
-	if (filebehave == FILE_GZIP)
-		nr = gzread(gzbufdesc, buffer, MAXBUFSIZ);
-	else if (filebehave == FILE_BZIP && bzbufdesc != NULL) {
-		nr = BZ2_bzRead(&bzerr, bzbufdesc, buffer, MAXBUFSIZ);
-		switch (bzerr) {
-		case BZ_OK:
-		case BZ_STREAM_END:
-			/* No problem, nr will be okay */
-			break;
-		case BZ_DATA_ERROR_MAGIC:
-			/*
-			 * As opposed to gzread(), which simply returns the
-			 * plain file data, if it is not in the correct
-			 * compressed format, BZ2_bzRead() instead aborts.
-			 *
-			 * So, just restart at the beginning of the file again,
-			 * and use plain reads from now on.
-			 */
-			BZ2_bzReadClose(&bzerr, bzbufdesc);
-			bzbufdesc = NULL;
-			if (lseek(f->fd, 0, SEEK_SET) == -1)
-				return (-1);
-			nr = read(f->fd, buffer, MAXBUFSIZ);
-			break;
-		default:
-			/* Make sure we exit with an error */
-			nr = -1;
-		}
-	} else
-#endif
-		nr = read(f->fd, buffer, MAXBUFSIZ);
-
-	if (nr < 0)
-		return (-1);
-
-	bufrem = nr;
-	return (0);
-}
-
-static inline int
-grep_lnbufgrow(size_t newlen)
-{
-
-	if (lnbuflen < newlen) {
-		lnbuf = grep_realloc(lnbuf, newlen);
-		lnbuflen = newlen;
-	}
-
-	return (0);
-}
-
-char *
-grep_fgetln(struct file *f, size_t *lenp)
-{
-	unsigned char *p;
-	char *ret;
-	size_t len;
-	size_t off;
-	ptrdiff_t diff;
-
-	/* Fill the buffer, if necessary */
-	if (bufrem == 0 && grep_refill(f) != 0)
-		goto error;
-
-	if (bufrem == 0) {
-		/* Return zero length to indicate EOF */
-		*lenp = 0;
-		return ((char *)bufpos);
-	}
-
-	/* Look for a newline in the remaining part of the buffer */
-	if ((p = memchr(bufpos, line_sep, bufrem)) != NULL) {
-		++p; /* advance over newline */
-		ret = (char *)bufpos;
-		len = p - bufpos;
-		bufrem -= len;
-		bufpos = p;
-		*lenp = len;
-		return (ret);
-	}
-
-	/* We have to copy the current buffered data to the line buffer */
-	for (len = bufrem, off = 0; ; len += bufrem) {
-		/* Make sure there is room for more data */
-		if (grep_lnbufgrow(len + LNBUFBUMP))
-			goto error;
-		memcpy(lnbuf + off, bufpos, len - off);
-		off = len;
-		if (grep_refill(f) != 0)
-			goto error;
-		if (bufrem == 0)
-			/* EOF: return partial line */
-			break;
-		if ((p = memchr(bufpos, line_sep, bufrem)) == NULL)
-			continue;
-		/* got it: finish up the line (like code above) */
-		++p;
-		diff = p - bufpos;
-		len += diff;
-		if (grep_lnbufgrow(len))
-		    goto error;
-		memcpy(lnbuf + off, bufpos, diff);
-		bufrem -= diff;
-		bufpos = p;
-		break;
-	}
-	*lenp = len;
-	return ((char *)lnbuf);
-
-error:
-	*lenp = 0;
-	return (NULL);
-}
-
-static inline struct file *
-grep_file_init(struct file *f)
-{
-
-#ifndef __ANDROID__
-	if (filebehave == FILE_GZIP &&
-	    (gzbufdesc = gzdopen(f->fd, "r")) == NULL)
-		goto error;
-
-	if (filebehave == FILE_BZIP &&
-	    (bzbufdesc = BZ2_bzdopen(f->fd, "r")) == NULL)
-		goto error;
-#endif
-
-	/* Fill read buffer, also catches errors early */
-	if (grep_refill(f) != 0)
-		goto error;
-
-	/* Check for binary stuff, if necessary */
-	if (!nulldataflag && binbehave != BINFILE_TEXT &&
-	    memchr(bufpos, '\0', bufrem) != NULL)
-		f->binary = true;
-
-	return (f);
-error:
-	close(f->fd);
-	free(f);
-	return (NULL);
-}
-
-/*
- * Opens a file for processing.
- */
-struct file *
-grep_open(const char *path)
-{
-	struct file *f;
-
-	f = grep_malloc(sizeof *f);
-	memset(f, 0, sizeof *f);
-	if (path == NULL) {
-		/* Processing stdin implies --line-buffered. */
-		lbflag = true;
-		f->fd = STDIN_FILENO;
-	} else if ((f->fd = open(path, O_RDONLY)) == -1) {
-		free(f);
-		return (NULL);
-	}
-
-	return (grep_file_init(f));
-}
-
-/*
- * Closes a file.
- */
-void
-grep_close(struct file *f)
-{
-
-	close(f->fd);
-
-	/* Reset read buffer and line buffer */
-	bufpos = buffer;
-	bufrem = 0;
-
-	free(lnbuf);
-	lnbuf = NULL;
-	lnbuflen = 0;
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/grep.c b/toolbox/upstream-netbsd/usr.bin/grep/grep.c
deleted file mode 100644
index 1ea6ed3..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.c
+++ /dev/null
@@ -1,707 +0,0 @@
-/*	$NetBSD: grep.c,v 1.12 2014/07/11 16:30:45 christos Exp $	*/
-/* 	$FreeBSD: head/usr.bin/grep/grep.c 211519 2010-08-19 22:55:17Z delphij $	*/
-/*	$OpenBSD: grep.c,v 1.42 2010/07/02 22:18:03 tedu Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: grep.c,v 1.12 2014/07/11 16:30:45 christos Exp $");
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <libgen.h>
-#include <locale.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "grep.h"
-
-#ifndef WITHOUT_NLS
-#include <nl_types.h>
-nl_catd	 catalog;
-#endif
-
-/*
- * Default messags to use when NLS is disabled or no catalogue
- * is found.
- */
-const char	*errstr[] = {
-	"",
-/* 1*/	"(standard input)",
-/* 2*/	"cannot read bzip2 compressed file",
-/* 3*/	"unknown %s option",
-/* 4*/	"usage: %s [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZz] [-A num] [-B num] [-C[num]]\n",
-/* 5*/	"\t[-e pattern] [-f file] [--binary-files=value] [--color=when]\n",
-/* 6*/	"\t[--context[=num]] [--directories=action] [--label] [--line-buffered]\n",
-/* 7*/	"\t[pattern] [file ...]\n",
-/* 8*/	"Binary file %s matches\n",
-/* 9*/	"%s (BSD grep) %s\n",
-};
-
-/* Flags passed to regcomp() and regexec() */
-int		 cflags = 0;
-int		 eflags = REG_STARTEND;
-
-/* Searching patterns */
-unsigned int	 patterns, pattern_sz;
-char		**pattern;
-regex_t		*r_pattern;
-fastgrep_t	*fg_pattern;
-
-/* Filename exclusion/inclusion patterns */
-unsigned int	 fpatterns, fpattern_sz;
-unsigned int	 dpatterns, dpattern_sz;
-struct epat	*dpattern, *fpattern;
-
-/* For regex errors  */
-char	 re_error[RE_ERROR_BUF + 1];
-
-/* Command-line flags */
-unsigned long long Aflag;	/* -A x: print x lines trailing each match */
-unsigned long long Bflag;	/* -B x: print x lines leading each match */
-bool	 Hflag;		/* -H: always print file name */
-bool	 Lflag;		/* -L: only show names of files with no matches */
-bool	 bflag;		/* -b: show block numbers for each match */
-bool	 cflag;		/* -c: only show a count of matching lines */
-bool	 hflag;		/* -h: don't print filename headers */
-bool	 iflag;		/* -i: ignore case */
-bool	 lflag;		/* -l: only show names of files with matches */
-bool	 mflag;		/* -m x: stop reading the files after x matches */
-unsigned long long mcount;	/* count for -m */
-bool	 nflag;		/* -n: show line numbers in front of matching lines */
-bool	 oflag;		/* -o: print only matching part */
-bool	 qflag;		/* -q: quiet mode (don't output anything) */
-bool	 sflag;		/* -s: silent mode (ignore errors) */
-bool	 vflag;		/* -v: only show non-matching lines */
-bool	 wflag;		/* -w: pattern must start and end on word boundaries */
-bool	 xflag;		/* -x: pattern must match entire line */
-bool	 lbflag;	/* --line-buffered */
-bool	 nullflag;	/* --null */
-bool	 nulldataflag;	/* --null-data */
-unsigned char line_sep = '\n';	/* 0 for --null-data */
-char	*label;		/* --label */
-const char *color;	/* --color */
-int	 grepbehave = GREP_BASIC;	/* -EFGP: type of the regex */
-int	 binbehave = BINFILE_BIN;	/* -aIU: handling of binary files */
-int	 filebehave = FILE_STDIO;	/* -JZ: normal, gzip or bzip2 file */
-int	 devbehave = DEV_READ;		/* -D: handling of devices */
-int	 dirbehave = DIR_READ;		/* -dRr: handling of directories */
-int	 linkbehave = LINK_READ;	/* -OpS: handling of symlinks */
-
-bool	 dexclude, dinclude;	/* --exclude-dir and --include-dir */
-bool	 fexclude, finclude;	/* --exclude and --include */
-
-enum {
-	BIN_OPT = CHAR_MAX + 1,
-	COLOR_OPT,
-	DECOMPRESS_OPT,
-	HELP_OPT,
-	MMAP_OPT,
-	LINEBUF_OPT,
-	LABEL_OPT,
-	R_EXCLUDE_OPT,
-	R_INCLUDE_OPT,
-	R_DEXCLUDE_OPT,
-	R_DINCLUDE_OPT
-};
-
-static inline const char	*init_color(const char *);
-
-/* Housekeeping */
-int	 tail;		/* lines left to print */
-bool	 notfound;	/* file not found */
-
-extern char	*__progname;
-
-/*
- * Prints usage information and returns 2.
- */
-__dead static void
-usage(void)
-{
-	fprintf(stderr, getstr(4), __progname);
-	fprintf(stderr, "%s", getstr(5));
-	fprintf(stderr, "%s", getstr(6));
-	fprintf(stderr, "%s", getstr(7));
-	exit(2);
-}
-
-static const char optstr[] =
-    "0123456789A:B:C:D:EFGHIJLOPSRUVZabcd:e:f:hilm:nopqrsuvwxyz";
-
-struct option long_options[] =
-{
-	{"binary-files",	required_argument,	NULL, BIN_OPT},
-	{"decompress",          no_argument,            NULL, DECOMPRESS_OPT},
-	{"help",		no_argument,		NULL, HELP_OPT},
-	{"mmap",		no_argument,		NULL, MMAP_OPT},
-	{"line-buffered",	no_argument,		NULL, LINEBUF_OPT},
-	{"label",		required_argument,	NULL, LABEL_OPT},
-	{"color",		optional_argument,	NULL, COLOR_OPT},
-	{"colour",		optional_argument,	NULL, COLOR_OPT},
-	{"exclude",		required_argument,	NULL, R_EXCLUDE_OPT},
-	{"include",		required_argument,	NULL, R_INCLUDE_OPT},
-	{"exclude-dir",		required_argument,	NULL, R_DEXCLUDE_OPT},
-	{"include-dir",		required_argument,	NULL, R_DINCLUDE_OPT},
-	{"after-context",	required_argument,	NULL, 'A'},
-	{"text",		no_argument,		NULL, 'a'},
-	{"before-context",	required_argument,	NULL, 'B'},
-	{"byte-offset",		no_argument,		NULL, 'b'},
-	{"context",		optional_argument,	NULL, 'C'},
-	{"count",		no_argument,		NULL, 'c'},
-	{"devices",		required_argument,	NULL, 'D'},
-        {"directories",		required_argument,	NULL, 'd'},
-	{"extended-regexp",	no_argument,		NULL, 'E'},
-	{"regexp",		required_argument,	NULL, 'e'},
-	{"fixed-strings",	no_argument,		NULL, 'F'},
-	{"file",		required_argument,	NULL, 'f'},
-	{"basic-regexp",	no_argument,		NULL, 'G'},
-	{"no-filename",		no_argument,		NULL, 'h'},
-	{"with-filename",	no_argument,		NULL, 'H'},
-	{"ignore-case",		no_argument,		NULL, 'i'},
-	{"bz2decompress",	no_argument,		NULL, 'J'},
-	{"files-with-matches",	no_argument,		NULL, 'l'},
-	{"files-without-match", no_argument,            NULL, 'L'},
-	{"max-count",		required_argument,	NULL, 'm'},
-	{"line-number",		no_argument,		NULL, 'n'},
-	{"only-matching",	no_argument,		NULL, 'o'},
-	{"quiet",		no_argument,		NULL, 'q'},
-	{"silent",		no_argument,		NULL, 'q'},
-	{"recursive",		no_argument,		NULL, 'r'},
-	{"no-messages",		no_argument,		NULL, 's'},
-	{"binary",		no_argument,		NULL, 'U'},
-	{"unix-byte-offsets",	no_argument,		NULL, 'u'},
-	{"invert-match",	no_argument,		NULL, 'v'},
-	{"version",		no_argument,		NULL, 'V'},
-	{"word-regexp",		no_argument,		NULL, 'w'},
-	{"line-regexp",		no_argument,		NULL, 'x'},
-	{"null",		no_argument,		NULL, 'Z'},
-	{"null-data",		no_argument,		NULL, 'z'},
-	{NULL,			no_argument,		NULL, 0}
-};
-
-/*
- * Adds a searching pattern to the internal array.
- */
-static void
-add_pattern(char *pat, size_t len)
-{
-
-	/* TODO: Check for empty patterns and shortcut */
-
-	/* Increase size if necessary */
-	if (patterns == pattern_sz) {
-		pattern_sz *= 2;
-		pattern = grep_realloc(pattern, ++pattern_sz *
-		    sizeof(*pattern));
-	}
-	if (len > 0 && pat[len - 1] == '\n')
-		--len;
-	/* pat may not be NUL-terminated */
-	pattern[patterns] = grep_malloc(len + 1);
-	memcpy(pattern[patterns], pat, len);
-	pattern[patterns][len] = '\0';
-	++patterns;
-}
-
-/*
- * Adds a file include/exclude pattern to the internal array.
- */
-static void
-add_fpattern(const char *pat, int mode)
-{
-
-	/* Increase size if necessary */
-	if (fpatterns == fpattern_sz) {
-		fpattern_sz *= 2;
-		fpattern = grep_realloc(fpattern, ++fpattern_sz *
-		    sizeof(struct epat));
-	}
-	fpattern[fpatterns].pat = grep_strdup(pat);
-	fpattern[fpatterns].mode = mode;
-	++fpatterns;
-}
-
-/*
- * Adds a directory include/exclude pattern to the internal array.
- */
-static void
-add_dpattern(const char *pat, int mode)
-{
-
-	/* Increase size if necessary */
-	if (dpatterns == dpattern_sz) {
-		dpattern_sz *= 2;
-		dpattern = grep_realloc(dpattern, ++dpattern_sz *
-		    sizeof(struct epat));
-	}
-	dpattern[dpatterns].pat = grep_strdup(pat);
-	dpattern[dpatterns].mode = mode;
-	++dpatterns;
-}
-
-/*
- * Reads searching patterns from a file and adds them with add_pattern().
- */
-static void
-read_patterns(const char *fn)
-{
-	FILE *f;
-	char *line;
-	size_t len;
-	ssize_t rlen;
-
-	if ((f = fopen(fn, "r")) == NULL)
-		err(2, "%s", fn);
-	line = NULL;
-	len = 0;
-	while ((rlen = getline(&line, &len, f)) != -1)
-		add_pattern(line, *line == '\n' ? 0 : (size_t)rlen);
-	free(line);
-	if (ferror(f))
-		err(2, "%s", fn);
-	fclose(f);
-}
-
-static inline const char *
-init_color(const char *d)
-{
-	char *c;
-
-	c = getenv("GREP_COLOR");
-	return (c != NULL ? c : d);
-}
-
-int
-main(int argc, char *argv[])
-{
-	char **aargv, **eargv, *eopts;
-	char *ep;
-	unsigned long long l;
-	unsigned int aargc, eargc, i, j;
-	int c, lastc, needpattern, newarg, prevoptind;
-
-	setlocale(LC_ALL, "");
-
-#ifndef WITHOUT_NLS
-	catalog = catopen("grep", NL_CAT_LOCALE);
-#endif
-
-	/* Check what is the program name of the binary.  In this
-	   way we can have all the funcionalities in one binary
-	   without the need of scripting and using ugly hacks. */
-	switch (__progname[0]) {
-	case 'e':
-		grepbehave = GREP_EXTENDED;
-		break;
-	case 'f':
-		grepbehave = GREP_FIXED;
-		break;
-	case 'g':
-		grepbehave = GREP_BASIC;
-		break;
-	case 'z':
-		filebehave = FILE_GZIP;
-		switch(__progname[1]) {
-		case 'e':
-			grepbehave = GREP_EXTENDED;
-			break;
-		case 'f':
-			grepbehave = GREP_FIXED;
-			break;
-		case 'g':
-			grepbehave = GREP_BASIC;
-			break;
-		}
-		break;
-	}
-
-	lastc = '\0';
-	newarg = 1;
-	prevoptind = 1;
-	needpattern = 1;
-
-	eopts = getenv("GREP_OPTIONS");
-
-	/* support for extra arguments in GREP_OPTIONS */
-	eargc = 0;
-	if (eopts != NULL) {
-		char *str;
-
-		/* make an estimation of how many extra arguments we have */
-		for (j = 0; j < strlen(eopts); j++)
-			if (eopts[j] == ' ')
-				eargc++;
-
-		eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1));
-
-		eargc = 0;
-		/* parse extra arguments */
-		while ((str = strsep(&eopts, " ")) != NULL)
-			eargv[eargc++] = grep_strdup(str);
-
-		aargv = (char **)grep_calloc(eargc + argc + 1,
-		    sizeof(char *));
-
-		aargv[0] = argv[0];
-		for (i = 0; i < eargc; i++)
-			aargv[i + 1] = eargv[i];
-		for (j = 1; j < (unsigned int)argc; j++, i++)
-			aargv[i + 1] = argv[j];
-
-		aargc = eargc + argc;
-	} else {
-		aargv = argv;
-		aargc = argc;
-	}
-
-	while (((c = getopt_long(aargc, aargv, optstr, long_options, NULL)) !=
-	    -1)) {
-		switch (c) {
-		case '0': case '1': case '2': case '3': case '4':
-		case '5': case '6': case '7': case '8': case '9':
-			if (newarg || !isdigit(lastc))
-				Aflag = 0;
-			else if (Aflag > LLONG_MAX / 10) {
-				errno = ERANGE;
-				err(2, NULL);
-			}
-			Aflag = Bflag = (Aflag * 10) + (c - '0');
-			break;
-		case 'C':
-			if (optarg == NULL) {
-				Aflag = Bflag = 2;
-				break;
-			}
-			/* FALLTHROUGH */
-		case 'A':
-			/* FALLTHROUGH */
-		case 'B':
-			errno = 0;
-			l = strtoull(optarg, &ep, 10);
-			if (((errno == ERANGE) && (l == ULLONG_MAX)) ||
-			    ((errno == EINVAL) && (l == 0)))
-				err(2, NULL);
-			else if (ep[0] != '\0') {
-				errno = EINVAL;
-				err(2, NULL);
-			}
-			if (c == 'A')
-				Aflag = l;
-			else if (c == 'B')
-				Bflag = l;
-			else
-				Aflag = Bflag = l;
-			break;
-		case 'a':
-			binbehave = BINFILE_TEXT;
-			break;
-		case 'b':
-			bflag = true;
-			break;
-		case 'c':
-			cflag = true;
-			break;
-		case 'D':
-			if (strcasecmp(optarg, "skip") == 0)
-				devbehave = DEV_SKIP;
-			else if (strcasecmp(optarg, "read") == 0)
-				devbehave = DEV_READ;
-			else
-				errx(2, getstr(3), "--devices");
-			break;
-		case 'd':
-			if (strcasecmp("recurse", optarg) == 0) {
-				Hflag = true;
-				dirbehave = DIR_RECURSE;
-			} else if (strcasecmp("skip", optarg) == 0)
-				dirbehave = DIR_SKIP;
-			else if (strcasecmp("read", optarg) == 0)
-				dirbehave = DIR_READ;
-			else
-				errx(2, getstr(3), "--directories");
-			break;
-		case 'E':
-			grepbehave = GREP_EXTENDED;
-			break;
-		case 'e':
-			add_pattern(optarg, strlen(optarg));
-			needpattern = 0;
-			break;
-		case 'F':
-			grepbehave = GREP_FIXED;
-			break;
-		case 'f':
-			read_patterns(optarg);
-			needpattern = 0;
-			break;
-		case 'G':
-			grepbehave = GREP_BASIC;
-			break;
-		case 'H':
-			Hflag = true;
-			break;
-		case 'h':
-			Hflag = false;
-			hflag = true;
-			break;
-		case 'I':
-			binbehave = BINFILE_SKIP;
-			break;
-		case 'i':
-		case 'y':
-			iflag =  true;
-			cflags |= REG_ICASE;
-			break;
-		case 'J':
-			filebehave = FILE_BZIP;
-			break;
-		case 'L':
-			lflag = false;
-			Lflag = true;
-			break;
-		case 'l':
-			Lflag = false;
-			lflag = true;
-			break;
-		case 'm':
-			mflag = true;
-			errno = 0;
-			mcount = strtoull(optarg, &ep, 10);
-			if (((errno == ERANGE) && (mcount == ULLONG_MAX)) ||
-			    ((errno == EINVAL) && (mcount == 0)))
-				err(2, NULL);
-			else if (ep[0] != '\0') {
-				errno = EINVAL;
-				err(2, NULL);
-			}
-			break;
-		case 'n':
-			nflag = true;
-			break;
-		case 'O':
-			linkbehave = LINK_EXPLICIT;
-			break;
-		case 'o':
-			oflag = true;
-			break;
-		case 'p':
-			linkbehave = LINK_SKIP;
-			break;
-		case 'q':
-			qflag = true;
-			break;
-		case 'S':
-			linkbehave = LINK_READ;
-			break;
-		case 'R':
-		case 'r':
-			dirbehave = DIR_RECURSE;
-			Hflag = true;
-			break;
-		case 's':
-			sflag = true;
-			break;
-		case 'U':
-			binbehave = BINFILE_BIN;
-			break;
-		case 'u':
-		case MMAP_OPT:
-			/* noop, compatibility */
-			break;
-		case 'V':
-			printf(getstr(9), __progname, VERSION);
-			exit(0);
-		case 'v':
-			vflag = true;
-			break;
-		case 'w':
-			wflag = true;
-			break;
-		case 'x':
-			xflag = true;
-			break;
-		case 'Z':
-			nullflag = true;
-			break;
-		case 'z':
-			nulldataflag = true;
-			line_sep = '\0';
-			break;
-		case BIN_OPT:
-			if (strcasecmp("binary", optarg) == 0)
-				binbehave = BINFILE_BIN;
-			else if (strcasecmp("without-match", optarg) == 0)
-				binbehave = BINFILE_SKIP;
-			else if (strcasecmp("text", optarg) == 0)
-				binbehave = BINFILE_TEXT;
-			else
-				errx(2, getstr(3), "--binary-files");
-			break;
-		case COLOR_OPT:
-			color = NULL;
-			if (optarg == NULL || strcasecmp("auto", optarg) == 0 ||
-			    strcasecmp("tty", optarg) == 0 ||
-			    strcasecmp("if-tty", optarg) == 0) {
-				char *term;
-
-				term = getenv("TERM");
-				if (isatty(STDOUT_FILENO) && term != NULL &&
-				    strcasecmp(term, "dumb") != 0)
-					color = init_color("01;31");
-			} else if (strcasecmp("always", optarg) == 0 ||
-			    strcasecmp("yes", optarg) == 0 ||
-			    strcasecmp("force", optarg) == 0) {
-				color = init_color("01;31");
-			} else if (strcasecmp("never", optarg) != 0 &&
-			    strcasecmp("none", optarg) != 0 &&
-			    strcasecmp("no", optarg) != 0)
-				errx(2, getstr(3), "--color");
-			break;
-		case DECOMPRESS_OPT:
-			filebehave = FILE_GZIP;
-			break;
-		case LABEL_OPT:
-			label = optarg;
-			break;
-		case LINEBUF_OPT:
-			lbflag = true;
-			break;
-		case R_INCLUDE_OPT:
-			finclude = true;
-			add_fpattern(optarg, INCL_PAT);
-			break;
-		case R_EXCLUDE_OPT:
-			fexclude = true;
-			add_fpattern(optarg, EXCL_PAT);
-			break;
-		case R_DINCLUDE_OPT:
-			dinclude = true;
-			add_dpattern(optarg, INCL_PAT);
-			break;
-		case R_DEXCLUDE_OPT:
-			dexclude = true;
-			add_dpattern(optarg, EXCL_PAT);
-			break;
-		case HELP_OPT:
-		default:
-			usage();
-		}
-		lastc = c;
-		newarg = optind != prevoptind;
-		prevoptind = optind;
-	}
-	aargc -= optind;
-	aargv += optind;
-
-	/* Fail if we don't have any pattern */
-	if (aargc == 0 && needpattern)
-		usage();
-
-	/* Process patterns from command line */
-	if (aargc != 0 && needpattern) {
-		add_pattern(*aargv, strlen(*aargv));
-		--aargc;
-		++aargv;
-	}
-
-	switch (grepbehave) {
-	case GREP_FIXED:
-	case GREP_BASIC:
-		break;
-	case GREP_EXTENDED:
-		cflags |= REG_EXTENDED;
-		break;
-	default:
-		/* NOTREACHED */
-		usage();
-	}
-
-	fg_pattern = grep_calloc(patterns, sizeof(*fg_pattern));
-	r_pattern = grep_calloc(patterns, sizeof(*r_pattern));
-/*
- * XXX: fgrepcomp() and fastcomp() are workarounds for regexec() performance.
- * Optimizations should be done there.
- */
-		/* Check if cheating is allowed (always is for fgrep). */
-	if (grepbehave == GREP_FIXED) {
-		for (i = 0; i < patterns; ++i)
-			fgrepcomp(&fg_pattern[i], pattern[i]);
-	} else {
-		for (i = 0; i < patterns; ++i) {
-			if (fastcomp(&fg_pattern[i], pattern[i])) {
-				/* Fall back to full regex library */
-				c = regcomp(&r_pattern[i], pattern[i], cflags);
-				if (c != 0) {
-					regerror(c, &r_pattern[i], re_error,
-					    RE_ERROR_BUF);
-					errx(2, "%s", re_error);
-				}
-			}
-		}
-	}
-
-	if (lbflag)
-		setlinebuf(stdout);
-
-	if ((aargc == 0 || aargc == 1) && !Hflag)
-		hflag = true;
-
-	if (aargc == 0)
-		exit(!procfile("-"));
-
-	if (dirbehave == DIR_RECURSE)
-		c = grep_tree(aargv);
-	else
-		for (c = 0; aargc--; ++aargv) {
-			if ((finclude || fexclude) && !file_matching(*aargv))
-				continue;
-			c+= procfile(*aargv);
-		}
-
-#ifndef WITHOUT_NLS
-	catclose(catalog);
-#endif
-
-	/* Find out the correct return value according to the
-	   results and the command line option. */
-	exit(c ? (notfound ? (qflag ? 0 : 2) : 0) : (notfound ? 2 : 1));
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/grep.h b/toolbox/upstream-netbsd/usr.bin/grep/grep.h
deleted file mode 100644
index fa2a3e3..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*	$NetBSD: grep.h,v 1.8 2012/05/06 22:27:00 joerg Exp $	*/
-/*	$OpenBSD: grep.h,v 1.15 2010/04/05 03:03:55 tedu Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/grep.h 211496 2010-08-19 09:28:59Z des $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (c) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef __ANDROID__
-#include <bzlib.h>
-#endif
-#include <limits.h>
-#include <regex.h>
-#include <stdbool.h>
-#include <stdio.h>
-#ifndef __ANDROID__
-#include <zlib.h>
-#endif
-
-#ifdef WITHOUT_NLS
-#define getstr(n)	 errstr[n]
-#else
-#include <nl_types.h>
-
-extern nl_catd		 catalog;
-#define getstr(n)	 catgets(catalog, 1, n, errstr[n])
-#endif
-
-extern const char		*errstr[];
-
-#define VERSION		"2.5.1-FreeBSD"
-
-#define GREP_FIXED	0
-#define GREP_BASIC	1
-#define GREP_EXTENDED	2
-
-#define BINFILE_BIN	0
-#define BINFILE_SKIP	1
-#define BINFILE_TEXT	2
-
-#define FILE_STDIO	0
-#define FILE_GZIP	1
-#define FILE_BZIP	2
-
-#define DIR_READ	0
-#define DIR_SKIP	1
-#define DIR_RECURSE	2
-
-#define DEV_READ	0
-#define DEV_SKIP	1
-
-#define LINK_READ	0
-#define LINK_EXPLICIT	1
-#define LINK_SKIP	2
-
-#define EXCL_PAT	0
-#define INCL_PAT	1
-
-#define MAX_LINE_MATCHES	32
-
-struct file {
-	int		 fd;
-	bool		 binary;
-};
-
-struct str {
-	off_t		 off;
-	size_t		 len;
-	char		*dat;
-	char		*file;
-	int		 line_no;
-};
-
-struct epat {
-	char		*pat;
-	int		 mode;
-};
-
-typedef struct {
-	size_t		 len;
-	unsigned char	*pattern;
-	int		 qsBc[UCHAR_MAX + 1];
-	/* flags */
-	bool		 bol;
-	bool		 eol;
-	bool		 reversed;
-	bool		 word;
-} fastgrep_t;
-
-/* Flags passed to regcomp() and regexec() */
-extern int	 cflags, eflags;
-
-/* Command line flags */
-extern bool	 Eflag, Fflag, Gflag, Hflag, Lflag,
-		 bflag, cflag, hflag, iflag, lflag, mflag, nflag, oflag,
-		 qflag, sflag, vflag, wflag, xflag;
-extern bool	 dexclude, dinclude, fexclude, finclude, lbflag, nullflag, nulldataflag;
-extern unsigned char line_sep;
-extern unsigned long long Aflag, Bflag, mcount;
-extern char	*label;
-extern const char *color;
-extern int	 binbehave, devbehave, dirbehave, filebehave, grepbehave, linkbehave;
-
-extern bool	 notfound;
-extern int	 tail;
-extern unsigned int dpatterns, fpatterns, patterns;
-extern char    **pattern;
-extern struct epat *dpattern, *fpattern;
-extern regex_t	*er_pattern, *r_pattern;
-extern fastgrep_t *fg_pattern;
-
-/* For regex errors  */
-#define RE_ERROR_BUF	512
-extern char	 re_error[RE_ERROR_BUF + 1];	/* Seems big enough */
-
-/* util.c */
-bool	 file_matching(const char *fname);
-int	 procfile(const char *fn);
-int	 grep_tree(char **argv);
-void	*grep_malloc(size_t size);
-void	*grep_calloc(size_t nmemb, size_t size);
-void	*grep_realloc(void *ptr, size_t size);
-char	*grep_strdup(const char *str);
-void	 printline(struct str *line, int sep, regmatch_t *matches, int m);
-
-/* queue.c */
-void	 enqueue(struct str *x);
-void	 printqueue(void);
-void	 clearqueue(void);
-
-/* file.c */
-void		 grep_close(struct file *f);
-struct file	*grep_open(const char *path);
-char		*grep_fgetln(struct file *f, size_t *len);
-
-/* fastgrep.c */
-int		 fastcomp(fastgrep_t *, const char *);
-void		 fgrepcomp(fastgrep_t *, const char *);
-int		 grep_search(fastgrep_t *, const unsigned char *, size_t, regmatch_t *);
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/queue.c b/toolbox/upstream-netbsd/usr.bin/grep/queue.c
deleted file mode 100644
index e3c6be1..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/queue.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*	$NetBSD: queue.c,v 1.5 2011/08/31 16:24:57 plunky Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/queue.c 211496 2010-08-19 09:28:59Z des $	*/
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * A really poor man's queue.  It does only what it has to and gets out of
- * Dodge.  It is used in place of <sys/queue.h> to get a better performance.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: queue.c,v 1.5 2011/08/31 16:24:57 plunky Exp $");
-
-#include <sys/param.h>
-#include <sys/queue.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "grep.h"
-
-struct qentry {
-	STAILQ_ENTRY(qentry)	list;
-	struct str	 	data;
-};
-
-static STAILQ_HEAD(, qentry)	queue = STAILQ_HEAD_INITIALIZER(queue);
-static unsigned long long	count;
-
-static struct qentry	*dequeue(void);
-
-void
-enqueue(struct str *x)
-{
-	struct qentry *item;
-
-	item = grep_malloc(sizeof(struct qentry));
-	item->data.dat = grep_malloc(sizeof(char) * x->len);
-	item->data.len = x->len;
-	item->data.line_no = x->line_no;
-	item->data.off = x->off;
-	memcpy(item->data.dat, x->dat, x->len);
-	item->data.file = x->file;
-
-	STAILQ_INSERT_TAIL(&queue, item, list);
-
-	if (++count > Bflag) {
-		item = dequeue();
-		free(item->data.dat);
-		free(item);
-	}
-}
-
-static struct qentry *
-dequeue(void)
-{
-	struct qentry *item;
-
-	item = STAILQ_FIRST(&queue);
-	if (item == NULL)
-		return (NULL);
-
-	STAILQ_REMOVE_HEAD(&queue, list);
-	--count;
-	return (item);
-}
-
-void
-printqueue(void)
-{
-	struct qentry *item;
-
-	while ((item = dequeue()) != NULL) {
-		printline(&item->data, '-', NULL, 0);
-		free(item->data.dat);
-		free(item);
-	}
-}
-
-void
-clearqueue(void)
-{
-	struct qentry *item;
-
-	while ((item = dequeue()) != NULL) {
-		free(item->data.dat);
-		free(item);
-	}
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/util.c b/toolbox/upstream-netbsd/usr.bin/grep/util.c
deleted file mode 100644
index ecd948d..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/util.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*	$NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/util.c 211496 2010-08-19 09:28:59Z des $	*/
-/*	$OpenBSD: util.c,v 1.39 2010/07/02 22:18:03 tedu Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $");
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fnmatch.h>
-#include <fts.h>
-#include <libgen.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "grep.h"
-
-static bool	 first, first_global = true;
-static unsigned long long since_printed;
-
-static int	 procline(struct str *l, int);
-
-bool
-file_matching(const char *fname)
-{
-	char *fname_base, *fname_copy;
-	unsigned int i;
-	bool ret;
-
-	ret = finclude ? false : true;
-	fname_copy = grep_strdup(fname);
-	fname_base = basename(fname_copy);
-
-	for (i = 0; i < fpatterns; ++i) {
-		if (fnmatch(fpattern[i].pat, fname, 0) == 0 ||
-		    fnmatch(fpattern[i].pat, fname_base, 0) == 0) {
-			if (fpattern[i].mode == EXCL_PAT) {
-				free(fname_copy);
-				return (false);
-			} else
-				ret = true;
-		}
-	}
-	free(fname_copy);
-	return (ret);
-}
-
-static inline bool
-dir_matching(const char *dname)
-{
-	unsigned int i;
-	bool ret;
-
-	ret = dinclude ? false : true;
-
-	for (i = 0; i < dpatterns; ++i) {
-		if (dname != NULL &&
-		    fnmatch(dname, dpattern[i].pat, 0) == 0) {
-			if (dpattern[i].mode == EXCL_PAT)
-				return (false);
-			else
-				ret = true;
-		}
-	}
-	return (ret);
-}
-
-/*
- * Processes a directory when a recursive search is performed with
- * the -R option.  Each appropriate file is passed to procfile().
- */
-int
-grep_tree(char **argv)
-{
-	FTS *fts;
-	FTSENT *p;
-	char *d, *dir = NULL;
-	int c, fts_flags;
-	bool ok;
-
-	c = fts_flags = 0;
-
-	switch(linkbehave) {
-	case LINK_EXPLICIT:
-		fts_flags = FTS_COMFOLLOW;
-		break;
-	case LINK_SKIP:
-		fts_flags = FTS_PHYSICAL;
-		break;
-	default:
-		fts_flags = FTS_LOGICAL;
-			
-	}
-
-	fts_flags |= FTS_NOSTAT | FTS_NOCHDIR;
-
-	if (!(fts = fts_open(argv, fts_flags, NULL)))
-		err(2, "fts_open");
-	while ((p = fts_read(fts)) != NULL) {
-		switch (p->fts_info) {
-		case FTS_DNR:
-			/* FALLTHROUGH */
-		case FTS_ERR:
-			errx(2, "%s: %s", p->fts_path, strerror(p->fts_errno));
-			break;
-		case FTS_D:
-			/* FALLTHROUGH */
-		case FTS_DP:
-			break;
-		case FTS_DC:
-			/* Print a warning for recursive directory loop */
-			warnx("warning: %s: recursive directory loop",
-				p->fts_path);
-			break;
-		default:
-			/* Check for file exclusion/inclusion */
-			ok = true;
-			if (dexclude || dinclude) {
-				if ((d = strrchr(p->fts_path, '/')) != NULL) {
-					dir = grep_malloc(sizeof(char) *
-					    (d - p->fts_path + 1));
-					memcpy(dir, p->fts_path,
-					    d - p->fts_path);
-					dir[d - p->fts_path] = '\0';
-				}
-				ok = dir_matching(dir);
-				free(dir);
-				dir = NULL;
-			}
-			if (fexclude || finclude)
-				ok &= file_matching(p->fts_path);
-
-			if (ok)
-				c += procfile(p->fts_path);
-			break;
-		}
-	}
-
-	fts_close(fts);
-	return (c);
-}
-
-/*
- * Opens a file and processes it.  Each file is processed line-by-line
- * passing the lines to procline().
- */
-int
-procfile(const char *fn)
-{
-	struct file *f;
-	struct stat sb;
-	struct str ln;
-	mode_t s;
-	int c, t;
-
-	if (mflag && (mcount <= 0))
-		return (0);
-
-	if (strcmp(fn, "-") == 0) {
-		fn = label != NULL ? label : getstr(1);
-		f = grep_open(NULL);
-	} else {
-		if (!stat(fn, &sb)) {
-			/* Check if we need to process the file */
-			s = sb.st_mode & S_IFMT;
-			if (s == S_IFDIR && dirbehave == DIR_SKIP)
-				return (0);
-			if ((s == S_IFIFO || s == S_IFCHR || s == S_IFBLK
-				|| s == S_IFSOCK) && devbehave == DEV_SKIP)
-					return (0);
-		}
-		f = grep_open(fn);
-	}
-	if (f == NULL) {
-		if (!sflag)
-			warn("%s", fn);
-		if (errno == ENOENT)
-			notfound = true;
-		return (0);
-	}
-
-	ln.file = grep_malloc(strlen(fn) + 1);
-	strcpy(ln.file, fn);
-	ln.line_no = 0;
-	ln.len = 0;
-	tail = 0;
-	ln.off = -1;
-
-	for (first = true, c = 0;  c == 0 || !(lflag || qflag); ) {
-		ln.off += ln.len + 1;
-		if ((ln.dat = grep_fgetln(f, &ln.len)) == NULL || ln.len == 0)
-			break;
-		if (ln.len > 0 && ln.dat[ln.len - 1] == line_sep)
-			--ln.len;
-		ln.line_no++;
-
-		/* Return if we need to skip a binary file */
-		if (f->binary && binbehave == BINFILE_SKIP) {
-			grep_close(f);
-			free(ln.file);
-			free(f);
-			return (0);
-		}
-		/* Process the file line-by-line */
-		t = procline(&ln, f->binary);
-		c += t;
-
-		/* Count the matches if we have a match limit */
-		if (mflag) {
-			mcount -= t;
-			if (mcount <= 0)
-				break;
-		}
-	}
-	if (Bflag > 0)
-		clearqueue();
-	grep_close(f);
-
-	if (cflag) {
-		if (!hflag)
-			printf("%s:", ln.file);
-		printf("%u%c", c, line_sep);
-	}
-	if (lflag && !qflag && c != 0)
-		printf("%s%c", fn, line_sep);
-	if (Lflag && !qflag && c == 0)
-		printf("%s%c", fn, line_sep);
-	if (c && !cflag && !lflag && !Lflag &&
-	    binbehave == BINFILE_BIN && f->binary && !qflag)
-		printf(getstr(8), fn);
-
-	free(ln.file);
-	free(f);
-	return (c);
-}
-
-#define iswword(x)	(iswalnum((x)) || (x) == L'_')
-
-/*
- * Processes a line comparing it with the specified patterns.  Each pattern
- * is looped to be compared along with the full string, saving each and every
- * match, which is necessary to colorize the output and to count the
- * matches.  The matching lines are passed to printline() to display the
- * appropriate output.
- */
-static int
-procline(struct str *l, int nottext)
-{
-	regmatch_t matches[MAX_LINE_MATCHES];
-	regmatch_t pmatch;
-	size_t st = 0;
-	unsigned int i;
-	int c = 0, m = 0, r = 0;
-
-	/* Loop to process the whole line */
-	while (st <= l->len) {
-		pmatch.rm_so = st;
-		pmatch.rm_eo = l->len;
-
-		/* Loop to compare with all the patterns */
-		for (i = 0; i < patterns; i++) {
-/*
- * XXX: grep_search() is a workaround for speed up and should be
- * removed in the future.  See fastgrep.c.
- */
-			if (fg_pattern[i].pattern) {
-				r = grep_search(&fg_pattern[i],
-				    (unsigned char *)l->dat,
-				    l->len, &pmatch);
-				r = (r == 0) ? 0 : REG_NOMATCH;
-				st = pmatch.rm_eo;
-			} else {
-				r = regexec(&r_pattern[i], l->dat, 1,
-				    &pmatch, eflags);
-				r = (r == 0) ? 0 : REG_NOMATCH;
-				st = pmatch.rm_eo;
-			}
-			if (r == REG_NOMATCH)
-				continue;
-			/* Check for full match */
-			if (xflag &&
-			    (pmatch.rm_so != 0 ||
-			     (size_t)pmatch.rm_eo != l->len))
-				continue;
-			/* Check for whole word match */
-			if (fg_pattern[i].word && pmatch.rm_so != 0) {
-				wchar_t wbegin, wend;
-
-				wbegin = wend = L' ';
-				if (pmatch.rm_so != 0 &&
-				    sscanf(&l->dat[pmatch.rm_so - 1],
-				    "%lc", &wbegin) != 1)
-					continue;
-				if ((size_t)pmatch.rm_eo != l->len &&
-				    sscanf(&l->dat[pmatch.rm_eo],
-				    "%lc", &wend) != 1)
-					continue;
-				if (iswword(wbegin) || iswword(wend))
-					continue;
-			}
-			c = 1;
-			if (m < MAX_LINE_MATCHES)
-				matches[m++] = pmatch;
-			/* matches - skip further patterns */
-			if ((color != NULL && !oflag) || qflag || lflag)
-				break;
-		}
-
-		if (vflag) {
-			c = !c;
-			break;
-		}
-		/* One pass if we are not recording matches */
-		if ((color != NULL && !oflag) || qflag || lflag)
-			break;
-
-		if (st == (size_t)pmatch.rm_so)
-			break; 	/* No matches */
-	}
-
-	if (c && binbehave == BINFILE_BIN && nottext)
-		return (c); /* Binary file */
-
-	/* Dealing with the context */
-	if ((tail || c) && !cflag && !qflag && !lflag && !Lflag) {
-		if (c) {
-			if ((Aflag || Bflag) && !first_global &&
-			    (first || since_printed > Bflag))
-				printf("--\n");
-			tail = Aflag;
-			if (Bflag > 0)
-				printqueue();
-			printline(l, ':', matches, m);
-		} else {
-			printline(l, '-', matches, m);
-			tail--;
-		}
-		first = false;
-		first_global = false;
-		since_printed = 0;
-	} else {
-		if (Bflag)
-			enqueue(l);
-		since_printed++;
-	}
-	return (c);
-}
-
-/*
- * Safe malloc() for internal use.
- */
-void *
-grep_malloc(size_t size)
-{
-	void *ptr;
-
-	if ((ptr = malloc(size)) == NULL)
-		err(2, "malloc");
-	return (ptr);
-}
-
-/*
- * Safe calloc() for internal use.
- */
-void *
-grep_calloc(size_t nmemb, size_t size)
-{
-	void *ptr;
-
-	if ((ptr = calloc(nmemb, size)) == NULL)
-		err(2, "calloc");
-	return (ptr);
-}
-
-/*
- * Safe realloc() for internal use.
- */
-void *
-grep_realloc(void *ptr, size_t size)
-{
-
-	if ((ptr = realloc(ptr, size)) == NULL)
-		err(2, "realloc");
-	return (ptr);
-}
-
-/*
- * Safe strdup() for internal use.
- */
-char *
-grep_strdup(const char *str)
-{
-	char *ret;
-
-	if ((ret = strdup(str)) == NULL)
-		err(2, "strdup");
-	return (ret);
-}
-
-/*
- * Prints a matching line according to the command line options.
- */
-void
-printline(struct str *line, int sep, regmatch_t *matches, int m)
-{
-	size_t a = 0;
-	int i, n = 0;
-
-	if (!hflag) {
-		if (nullflag == 0)
-			fputs(line->file, stdout);
-		else {
-			printf("%s", line->file);
-			putchar(0);
-		}
-		++n;
-	}
-	if (nflag) {
-		if (n > 0)
-			putchar(sep);
-		printf("%d", line->line_no);
-		++n;
-	}
-	if (bflag) {
-		if (n > 0)
-			putchar(sep);
-		printf("%lld", (long long)line->off);
-		++n;
-	}
-	if (n)
-		putchar(sep);
-	/* --color and -o */
-	if ((oflag || color) && m > 0) {
-		for (i = 0; i < m; i++) {
-			if (!oflag)
-				fwrite(line->dat + a, matches[i].rm_so - a, 1,
-				    stdout);
-			if (color) 
-				fprintf(stdout, "\33[%sm\33[K", color);
-
-				fwrite(line->dat + matches[i].rm_so, 
-				    matches[i].rm_eo - matches[i].rm_so, 1,
-				    stdout);
-			if (color) 
-				fprintf(stdout, "\33[m\33[K");
-			a = matches[i].rm_eo;
-			if (oflag)
-				putchar('\n');
-		}
-		if (!oflag) {
-			if (line->len - a > 0)
-				fwrite(line->dat + a, line->len - a, 1, stdout);
-			putchar(line_sep);
-		}
-	} else {
-		fwrite(line->dat, line->len, 1, stdout);
-		putchar(line_sep);
-	}
-}