Merge "Fix a few demangler issues."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 0e38897..ee3503b 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -474,13 +474,14 @@
             asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0);
             if (s) {
                 unsigned rid = p->msg.arg0;
-                p->len = p->msg.data_length;
 
-                if (s->enqueue(s, p) == 0) {
+                // TODO: Convert apacket::data to a type that we can move out of.
+                std::string copy(p->data, p->data + p->msg.data_length);
+
+                if (s->enqueue(s, std::move(copy)) == 0) {
                     D("Enqueue the socket");
                     send_ready(s->id, rid, t);
                 }
-                return;
             }
         }
         break;
diff --git a/adb/adb.h b/adb/adb.h
index b5d6bcb..c9c635a 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -73,11 +73,6 @@
 };
 
 struct apacket {
-    apacket* next;
-
-    size_t len;
-    char* ptr;
-
     amessage msg;
     char data[MAX_PAYLOAD];
 };
diff --git a/adb/adb_trace.cpp b/adb/adb_trace.cpp
index eac923d..a8ec5fb 100644
--- a/adb/adb_trace.cpp
+++ b/adb/adb_trace.cpp
@@ -42,7 +42,11 @@
                const char* message) {
     android::base::StderrLogger(id, severity, tag, file, line, message);
 #if !ADB_HOST
-    gLogdLogger(id, severity, tag, file, line, message);
+    // Only print logs of INFO or higher to logcat, so that `adb logcat` with adbd tracing on
+    // doesn't result in exponential logging.
+    if (severity >= android::base::INFO) {
+        gLogdLogger(id, severity, tag, file, line, message);
+    }
 #endif
 }
 
@@ -137,11 +141,15 @@
             // -1 is used for the special values "1" and "all" that enable all
             // tracing.
             adb_trace_mask = ~0;
-            return;
+            break;
         } else {
             adb_trace_mask |= 1 << flag->second;
         }
     }
+
+    if (adb_trace_mask != 0) {
+        android::base::SetMinimumLogSeverity(android::base::VERBOSE);
+    }
 }
 
 void adb_trace_init(char** argv) {
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index fc6560c..1d2c8c7 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -43,11 +43,11 @@
 #define VLOG_IS_ON(TAG) \
     ((adb_trace_mask & (1 << (TAG))) != 0)
 
-#define VLOG(TAG)         \
+#define VLOG(TAG)                 \
     if (LIKELY(!VLOG_IS_ON(TAG))) \
-        ;                 \
-    else                  \
-        LOG(INFO)
+        ;                         \
+    else                          \
+        LOG(DEBUG)
 
 // You must define TRACE_TAG before using this macro.
 #define D(...) \
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index f0dff06..0a8a85a 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -470,10 +470,9 @@
     free(s);
 }
 
-static int jdwp_socket_enqueue(asocket* s, apacket* p) {
+static int jdwp_socket_enqueue(asocket* s, std::string) {
     /* you can't write to this asocket */
     D("LS(%d): JDWP socket received data?", s->id);
-    put_apacket(p);
     s->peer->close(s->peer);
     return -1;
 }
@@ -486,9 +485,11 @@
      * on the second one, close the connection
      */
     if (!jdwp->pass) {
-        apacket* p = get_apacket();
-        p->len = jdwp_process_list((char*)p->data, s->get_max_payload());
-        peer->enqueue(peer, p);
+        std::string data;
+        data.resize(s->get_max_payload());
+        size_t len = jdwp_process_list(&data[0], data.size());
+        data.resize(len);
+        peer->enqueue(peer, std::move(data));
         jdwp->pass = true;
     } else {
         peer->close(peer);
@@ -524,17 +525,14 @@
 static std::vector<std::unique_ptr<JdwpTracker>> _jdwp_trackers;
 
 static void jdwp_process_list_updated(void) {
-    char buffer[1024];
-    int len = jdwp_process_list_msg(buffer, sizeof(buffer));
+    std::string data;
+    data.resize(1024);
+    data.resize(jdwp_process_list_msg(&data[0], data.size()));
 
     for (auto& t : _jdwp_trackers) {
-        apacket* p = get_apacket();
-        memcpy(p->data, buffer, len);
-        p->len = len;
-
         if (t->peer) {
             // The tracker might not have been connected yet.
-            t->peer->enqueue(t->peer, p);
+            t->peer->enqueue(t->peer, data);
         }
     }
 }
@@ -560,17 +558,17 @@
     JdwpTracker* t = (JdwpTracker*)s;
 
     if (t->need_initial) {
-        apacket* p = get_apacket();
+        std::string data;
+        data.resize(s->get_max_payload());
+        data.resize(jdwp_process_list_msg(&data[0], data.size()));
         t->need_initial = false;
-        p->len = jdwp_process_list_msg((char*)p->data, s->get_max_payload());
-        s->peer->enqueue(s->peer, p);
+        s->peer->enqueue(s->peer, std::move(data));
     }
 }
 
-static int jdwp_tracker_enqueue(asocket* s, apacket* p) {
+static int jdwp_tracker_enqueue(asocket* s, std::string) {
     /* you can't write to this socket */
     D("LS(%d): JDWP tracker received data?", s->id);
-    put_apacket(p);
     s->peer->close(s->peer);
     return -1;
 }
diff --git a/adb/range.h b/adb/range.h
new file mode 100644
index 0000000..7a0b822
--- /dev/null
+++ b/adb/range.h
@@ -0,0 +1,65 @@
+#pragma once
+
+/*
+ * 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 <string>
+
+#include <android-base/logging.h>
+
+struct Range {
+    explicit Range(std::string data) : data_(std::move(data)) {}
+
+    Range(const Range& copy) = delete;
+    Range& operator=(const Range& copy) = delete;
+
+    Range(Range&& move) = default;
+    Range& operator=(Range&& move) = default;
+
+    bool empty() const {
+        return size() == 0;
+    }
+
+    size_t size() const {
+        return data_.size() - begin_offset_ - end_offset_;
+    };
+
+    void drop_front(size_t n) {
+        CHECK_GE(size(), n);
+        begin_offset_ += n;
+    }
+
+    void drop_end(size_t n) {
+        CHECK_GE(size(), n);
+        end_offset_ += n;
+    }
+
+    char* data() {
+        return &data_[0] + begin_offset_;
+    }
+
+    std::string::iterator begin() {
+        return data_.begin() + begin_offset_;
+    }
+
+    std::string::iterator end() {
+        return data_.end() - end_offset_;
+    }
+
+    std::string data_;
+    size_t begin_offset_ = 0;
+    size_t end_offset_ = 0;
+};
diff --git a/adb/socket.h b/adb/socket.h
index 64d05a9..a1b52b3 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -19,9 +19,12 @@
 
 #include <stddef.h>
 
+#include <deque>
 #include <memory>
+#include <string>
 
 #include "fdevent.h"
+#include "range.h"
 
 struct apacket;
 class atransport;
@@ -31,12 +34,6 @@
  * remote asocket is bound to the protocol engine.
  */
 struct asocket {
-    /* chain pointers for the local/remote list of
-     * asockets that this asocket lives in
-     */
-    asocket* next;
-    asocket* prev;
-
     /* the unique identifier for this asocket
      */
     unsigned id;
@@ -65,9 +62,10 @@
     fdevent fde;
     int fd;
 
-    // queue of apackets waiting to be written
-    apacket* pkt_first;
-    apacket* pkt_last;
+    // queue of data waiting to be written
+    std::deque<Range> packet_queue;
+
+    std::string smart_socket_data;
 
     /* enqueue is called by our peer when it has data
      * for us.  It should return 0 if we can accept more
@@ -75,7 +73,7 @@
      * peer->ready() when we once again are ready to
      * receive data.
      */
-    int (*enqueue)(asocket* s, apacket* pkt);
+    int (*enqueue)(asocket* s, std::string data);
 
     /* ready is called by the peer when it is ready for
      * us to send data via enqueue again
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index f7c66db..04ad6f3 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -114,10 +114,10 @@
     ASSERT_TRUE(s != nullptr);
     arg->bytes_written = 0;
     while (true) {
-        apacket* p = get_apacket();
-        p->len = sizeof(p->data);
-        arg->bytes_written += p->len;
-        int ret = s->enqueue(s, p);
+        std::string data;
+        data.resize(MAX_PAYLOAD);
+        arg->bytes_written += data.size();
+        int ret = s->enqueue(s, std::move(data));
         if (ret == 1) {
             // The writer has one packet waiting to send.
             break;
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index c53fbb4..e9c45b7 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -37,32 +37,28 @@
 
 #include "adb.h"
 #include "adb_io.h"
+#include "range.h"
 #include "transport.h"
 
 static std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
 static unsigned local_socket_next_id = 1;
 
-static asocket local_socket_list = {
-    .next = &local_socket_list, .prev = &local_socket_list,
-};
+static auto& local_socket_list = *new std::vector<asocket*>();
 
 /* the the list of currently closing local sockets.
 ** these have no peer anymore, but still packets to
 ** write to their fd.
 */
-static asocket local_socket_closing_list = {
-    .next = &local_socket_closing_list, .prev = &local_socket_closing_list,
-};
+static auto& local_socket_closing_list = *new std::vector<asocket*>();
 
 // Parse the global list of sockets to find one with id |local_id|.
 // If |peer_id| is not 0, also check that it is connected to a peer
 // with id |peer_id|. Returns an asocket handle on success, NULL on failure.
 asocket* find_local_socket(unsigned local_id, unsigned peer_id) {
-    asocket* s;
-    asocket* result = NULL;
+    asocket* result = nullptr;
 
     std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
-    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+    for (asocket* s : local_socket_list) {
         if (s->id != local_id) {
             continue;
         }
@@ -75,13 +71,6 @@
     return result;
 }
 
-static void insert_local_socket(asocket* s, asocket* list) {
-    s->next = list;
-    s->prev = s->next->prev;
-    s->prev->next = s;
-    s->next->prev = s;
-}
-
 void install_local_socket(asocket* s) {
     std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
 
@@ -92,29 +81,24 @@
         fatal("local socket id overflow");
     }
 
-    insert_local_socket(s, &local_socket_list);
+    local_socket_list.push_back(s);
 }
 
 void remove_socket(asocket* s) {
     std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
-    if (s->prev && s->next) {
-        s->prev->next = s->next;
-        s->next->prev = s->prev;
-        s->next = 0;
-        s->prev = 0;
-        s->id = 0;
+    for (auto list : { &local_socket_list, &local_socket_closing_list }) {
+        list->erase(std::remove_if(list->begin(), list->end(), [s](asocket* x) { return x == s; }),
+                    list->end());
     }
 }
 
 void close_all_sockets(atransport* t) {
-    asocket* s;
-
     /* this is a little gross, but since s->close() *will* modify
     ** the list out from under you, your options are limited.
     */
     std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
 restart:
-    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+    for (asocket* s : local_socket_list) {
         if (s->transport == t || (s->peer && s->peer->transport == t)) {
             s->close(s);
             goto restart;
@@ -122,55 +106,47 @@
     }
 }
 
-static int local_socket_enqueue(asocket* s, apacket* p) {
-    D("LS(%d): enqueue %zu", s->id, p->len);
+static int local_socket_enqueue(asocket* s, std::string data) {
+    D("LS(%d): enqueue %zu", s->id, data.size());
 
-    p->ptr = p->data;
+    Range r(std::move(data));
 
     /* if there is already data queue'd, we will receive
     ** events when it's time to write.  just add this to
     ** the tail
     */
-    if (s->pkt_first) {
+    if (!s->packet_queue.empty()) {
         goto enqueue;
     }
 
     /* write as much as we can, until we
     ** would block or there is an error/eof
     */
-    while (p->len > 0) {
-        int r = adb_write(s->fd, p->ptr, p->len);
-        if (r > 0) {
-            p->len -= r;
-            p->ptr += r;
+    while (!r.empty()) {
+        int rc = adb_write(s->fd, r.data(), r.size());
+        if (rc > 0) {
+            r.drop_front(rc);
             continue;
         }
-        if ((r == 0) || (errno != EAGAIN)) {
+
+        if (rc == 0 || errno != EAGAIN) {
             D("LS(%d): not ready, errno=%d: %s", s->id, errno, strerror(errno));
-            put_apacket(p);
             s->has_write_error = true;
             s->close(s);
             return 1; /* not ready (error) */
         } else {
+            // errno == EAGAIN
             break;
         }
     }
 
-    if (p->len == 0) {
-        put_apacket(p);
+    if (r.empty()) {
         return 0; /* ready for more data */
     }
 
 enqueue:
-    p->next = 0;
-    if (s->pkt_first) {
-        s->pkt_last->next = p;
-    } else {
-        s->pkt_first = p;
-    }
-    s->pkt_last = p;
-
     /* make sure we are notified when we can drain the queue */
+    s->packet_queue.push_back(std::move(r));
     fdevent_add(&s->fde, FDE_WRITE);
 
     return 1; /* not ready (backlog) */
@@ -184,7 +160,6 @@
 
 // be sure to hold the socket list lock when calling this
 static void local_socket_destroy(asocket* s) {
-    apacket *p, *n;
     int exit_on_close = s->exit_on_close;
 
     D("LS(%d): destroying fde.fd=%d", s->id, s->fde.fd);
@@ -194,12 +169,6 @@
     */
     fdevent_remove(&s->fde);
 
-    /* dispose of any unwritten data */
-    for (p = s->pkt_first; p; p = n) {
-        D("LS(%d): discarding %zu bytes", s->id, p->len);
-        n = p->next;
-        put_apacket(p);
-    }
     remove_socket(s);
     free(s);
 
@@ -229,7 +198,7 @@
     /* If we are already closing, or if there are no
     ** pending packets, destroy immediately
     */
-    if (s->closing || s->has_write_error || s->pkt_first == NULL) {
+    if (s->closing || s->has_write_error || s->packet_queue.empty()) {
         int id = s->id;
         local_socket_destroy(s);
         D("LS(%d): closed", id);
@@ -243,7 +212,7 @@
     fdevent_del(&s->fde, FDE_READ);
     remove_socket(s);
     D("LS(%d): put on socket_closing_list fd=%d", s->id, s->fd);
-    insert_local_socket(s, &local_socket_closing_list);
+    local_socket_closing_list.push_back(s);
     CHECK_EQ(FDE_WRITE, s->fde.state & FDE_WRITE);
 }
 
@@ -255,35 +224,30 @@
     ** in order to simplify the code.
     */
     if (ev & FDE_WRITE) {
-        apacket* p;
-        while ((p = s->pkt_first) != nullptr) {
-            while (p->len > 0) {
-                int r = adb_write(fd, p->ptr, p->len);
-                if (r == -1) {
+        while (!s->packet_queue.empty()) {
+            Range& r = s->packet_queue.front();
+            while (!r.empty()) {
+                int rc = adb_write(fd, r.data(), r.size());
+                if (rc == -1) {
                     /* returning here is ok because FDE_READ will
                     ** be processed in the next iteration loop
                     */
                     if (errno == EAGAIN) {
                         return;
                     }
-                } else if (r > 0) {
-                    p->ptr += r;
-                    p->len -= r;
+                } else if (rc > 0) {
+                    r.drop_front(rc);
                     continue;
                 }
 
-                D(" closing after write because r=%d and errno is %d", r, errno);
+                D(" closing after write because rc=%d and errno is %d", rc, errno);
                 s->has_write_error = true;
                 s->close(s);
                 return;
             }
 
-            if (p->len == 0) {
-                s->pkt_first = p->next;
-                if (s->pkt_first == 0) {
-                    s->pkt_last = 0;
-                }
-                put_apacket(p);
+            if (r.empty()) {
+                s->packet_queue.pop_front();
             }
         }
 
@@ -305,9 +269,10 @@
     }
 
     if (ev & FDE_READ) {
-        apacket* p = get_apacket();
-        char* x = p->data;
         const size_t max_payload = s->get_max_payload();
+        std::string data;
+        data.resize(max_payload);
+        char* x = &data[0];
         size_t avail = max_payload;
         int r = 0;
         int is_eof = 0;
@@ -332,16 +297,15 @@
         }
         D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d", s->id, s->fd, r, is_eof,
           s->fde.force_eof);
-        if ((avail == max_payload) || (s->peer == 0)) {
-            put_apacket(p);
-        } else {
-            p->len = max_payload - avail;
+
+        if (avail != max_payload && s->peer) {
+            data.resize(max_payload - avail);
 
             // s->peer->enqueue() may call s->close() and free s,
             // so save variables for debug printing below.
             unsigned saved_id = s->id;
             int saved_fd = s->fd;
-            r = s->peer->enqueue(s->peer, p);
+            r = s->peer->enqueue(s->peer, std::move(data));
             D("LS(%u): fd=%d post peer->enqueue(). r=%d", saved_id, saved_fd, r);
 
             if (r < 0) {
@@ -445,12 +409,22 @@
 }
 #endif /* ADB_HOST */
 
-static int remote_socket_enqueue(asocket* s, apacket* p) {
+static int remote_socket_enqueue(asocket* s, std::string data) {
     D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
+    apacket* p = get_apacket();
+
     p->msg.command = A_WRTE;
     p->msg.arg0 = s->peer->id;
     p->msg.arg1 = s->id;
-    p->msg.data_length = p->len;
+    p->msg.data_length = data.size();
+
+    if (data.size() > sizeof(p->data)) {
+        put_apacket(p);
+        return -1;
+    }
+
+    // TODO: Convert apacket::data to a type that we can move into.
+    memcpy(p->data, data.data(), data.size());
     send_packet(p, s->transport);
     return 1;
 }
@@ -550,7 +524,7 @@
     s->close(s);
 }
 
-static unsigned unhex(char* s, int len) {
+static unsigned unhex(const char* s, int len) {
     unsigned n = 0, c;
 
     while (len-- > 0) {
@@ -654,8 +628,7 @@
 
 #endif  // ADB_HOST
 
-static int smart_socket_enqueue(asocket* s, apacket* p) {
-    unsigned len;
+static int smart_socket_enqueue(asocket* s, std::string data) {
 #if ADB_HOST
     char* service = nullptr;
     char* serial = nullptr;
@@ -663,49 +636,38 @@
     TransportType type = kTransportAny;
 #endif
 
-    D("SS(%d): enqueue %zu", s->id, p->len);
+    D("SS(%d): enqueue %zu", s->id, data.size());
 
-    if (s->pkt_first == 0) {
-        s->pkt_first = p;
-        s->pkt_last = p;
+    if (s->smart_socket_data.empty()) {
+        s->smart_socket_data = std::move(data);
     } else {
-        if ((s->pkt_first->len + p->len) > s->get_max_payload()) {
-            D("SS(%d): overflow", s->id);
-            put_apacket(p);
-            goto fail;
-        }
-
-        memcpy(s->pkt_first->data + s->pkt_first->len, p->data, p->len);
-        s->pkt_first->len += p->len;
-        put_apacket(p);
-
-        p = s->pkt_first;
+        std::copy(data.begin(), data.end(), std::back_inserter(s->smart_socket_data));
     }
 
     /* don't bother if we can't decode the length */
-    if (p->len < 4) {
+    if (s->smart_socket_data.size() < 4) {
         return 0;
     }
 
-    len = unhex(p->data, 4);
-    if ((len < 1) || (len > MAX_PAYLOAD)) {
-        D("SS(%d): bad size (%d)", s->id, len);
+    uint32_t len = unhex(s->smart_socket_data.data(), 4);
+    if (len == 0 || len > MAX_PAYLOAD) {
+        D("SS(%d): bad size (%u)", s->id, len);
         goto fail;
     }
 
-    D("SS(%d): len is %d", s->id, len);
+    D("SS(%d): len is %u", s->id, len);
     /* can't do anything until we have the full header */
-    if ((len + 4) > p->len) {
-        D("SS(%d): waiting for %zu more bytes", s->id, len + 4 - p->len);
+    if ((len + 4) > s->smart_socket_data.size()) {
+        D("SS(%d): waiting for %zu more bytes", s->id, len + 4 - s->smart_socket_data.size());
         return 0;
     }
 
-    p->data[len + 4] = 0;
+    s->smart_socket_data[len + 4] = 0;
 
-    D("SS(%d): '%s'", s->id, (char*)(p->data + 4));
+    D("SS(%d): '%s'", s->id, (char*)(s->smart_socket_data.data() + 4));
 
 #if ADB_HOST
-    service = (char*)p->data + 4;
+    service = &s->smart_socket_data[4];
     if (!strncmp(service, "host-serial:", strlen("host-serial:"))) {
         char* serial_end;
         service += strlen("host-serial:");
@@ -753,7 +715,7 @@
         }
         if (!strncmp(service, "transport", strlen("transport"))) {
             D("SS(%d): okay transport", s->id);
-            p->len = 0;
+            s->smart_socket_data.clear();
             return 0;
         }
 
@@ -824,7 +786,7 @@
     /* give him our transport and upref it */
     s->peer->transport = s->transport;
 
-    connect_to_remote(s->peer, (char*)(p->data + 4));
+    connect_to_remote(s->peer, s->smart_socket_data.data() + 4);
     s->peer = 0;
     s->close(s);
     return 1;
@@ -844,9 +806,6 @@
 
 static void smart_socket_close(asocket* s) {
     D("SS(%d): closed", s->id);
-    if (s->pkt_first) {
-        put_apacket(s->pkt_first);
-    }
     if (s->peer) {
         s->peer->peer = 0;
         s->peer->close(s->peer);
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 5acaaec..3b0669c 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -72,6 +72,11 @@
         return false;
     }
 
+    if (packet->msg.data_length > sizeof(packet->data)) {
+        D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
+        return false;
+    }
+
     if (!ReadFdExactly(fd_.get(), &packet->data, packet->msg.data_length)) {
         D("remote local: terminated (data)");
         return false;
@@ -409,21 +414,22 @@
     free(tracker);
 }
 
-static int device_tracker_enqueue(asocket* socket, apacket* p) {
+static int device_tracker_enqueue(asocket* socket, std::string) {
     /* you can't read from a device tracker, close immediately */
-    put_apacket(p);
     device_tracker_close(socket);
     return -1;
 }
 
 static int device_tracker_send(device_tracker* tracker, const std::string& string) {
-    apacket* p = get_apacket();
     asocket* peer = tracker->socket.peer;
 
-    snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
-    memcpy(&p->data[4], string.data(), string.size());
-    p->len = 4 + string.size();
-    return peer->enqueue(peer, p);
+    std::string data;
+    data.resize(4 + string.size());
+    char buf[5];
+    snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
+    memcpy(&data[0], buf, 4);
+    memcpy(&data[4], string.data(), string.size());
+    return peer->enqueue(peer, std::move(data));
 }
 
 static void device_tracker_ready(asocket* socket) {
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 73e8e15..a108699 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -61,6 +61,10 @@
 static int UsbReadPayload(usb_handle* h, apacket* p) {
     D("UsbReadPayload(%d)", p->msg.data_length);
 
+    if (p->msg.data_length > sizeof(p->data)) {
+        return -1;
+    }
+
 #if CHECK_PACKET_OVERFLOW
     size_t usb_packet_size = usb_get_max_packet_size(h);
     CHECK_EQ(0ULL, sizeof(p->data) % usb_packet_size);
@@ -116,6 +120,11 @@
     }
 
     if (p->msg.data_length) {
+        if (p->msg.data_length > sizeof(p->data)) {
+            PLOG(ERROR) << "remote usb: read overflow (data length = " << p->msg.data_length << ")";
+            return -1;
+        }
+
         if (usb_read(usb, p->data, p->msg.data_length)) {
             PLOG(ERROR) << "remote usb: terminated (data)";
             return -1;
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 5fddddc..364fca5 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -55,7 +55,7 @@
 using android::base::unique_fd;
 using unwindstack::Regs;
 
-extern "C" void __linker_enable_fallback_allocator();
+extern "C" bool __linker_enable_fallback_allocator();
 extern "C" void __linker_disable_fallback_allocator();
 
 // This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace
@@ -65,7 +65,11 @@
 // This isn't the default method of dumping because it can fail in cases such as address space
 // exhaustion.
 static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) {
-  __linker_enable_fallback_allocator();
+  if (!__linker_enable_fallback_allocator()) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use");
+    return;
+  }
+
   {
     std::unique_ptr<Regs> regs;
 
@@ -84,7 +88,11 @@
 
 static void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo,
                                          void* abort_message) {
-  __linker_enable_fallback_allocator();
+  if (!__linker_enable_fallback_allocator()) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use");
+    return;
+  }
+
   engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo,
                              ucontext);
   __linker_disable_fallback_allocator();
@@ -116,7 +124,7 @@
   closedir(dir);
 }
 
-static bool forward_output(int src_fd, int dst_fd) {
+static bool forward_output(int src_fd, int dst_fd, pid_t expected_tid) {
   // Make sure the thread actually got the signal.
   struct pollfd pfd = {
     .fd = src_fd, .events = POLLIN,
@@ -127,6 +135,18 @@
     return false;
   }
 
+  pid_t tid;
+  if (TEMP_FAILURE_RETRY(read(src_fd, &tid, sizeof(tid))) != sizeof(tid)) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to read tid");
+    return false;
+  }
+
+  if (tid != expected_tid) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "received tid %d, expected %d", tid,
+                          expected_tid);
+    return false;
+  }
+
   while (true) {
     char buf[512];
     ssize_t rc = TEMP_FAILURE_RETRY(read(src_fd, buf, sizeof(buf)));
@@ -144,16 +164,54 @@
   }
 }
 
+struct __attribute__((__packed__)) packed_thread_output {
+  int32_t tid;
+  int32_t fd;
+};
+
+static uint64_t pack_thread_fd(pid_t tid, int fd) {
+  packed_thread_output packed = {.tid = tid, .fd = fd};
+  uint64_t result;
+  static_assert(sizeof(packed) == sizeof(result));
+  memcpy(&result, &packed, sizeof(packed));
+  return result;
+}
+
+static std::pair<pid_t, int> unpack_thread_fd(uint64_t value) {
+  packed_thread_output result;
+  memcpy(&result, &value, sizeof(value));
+  return std::make_pair(result.tid, result.fd);
+}
+
 static void trace_handler(siginfo_t* info, ucontext_t* ucontext) {
-  static std::atomic<int> trace_output_fd(-1);
+  static std::atomic<uint64_t> trace_output(pack_thread_fd(-1, -1));
 
   if (info->si_value.sival_int == ~0) {
     // Asked to dump by the original signal recipient.
-    debuggerd_fallback_trace(trace_output_fd, ucontext);
+    uint64_t val = trace_output.load();
+    auto [tid, fd] = unpack_thread_fd(val);
+    if (tid != gettid()) {
+      // We received some other thread's info request?
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                            "thread %d received output fd for thread %d?", gettid(), tid);
+      return;
+    }
 
-    int tmp = trace_output_fd.load();
-    trace_output_fd.store(-1);
-    close(tmp);
+    if (!trace_output.compare_exchange_strong(val, pack_thread_fd(-1, -1))) {
+      // Presumably, the timeout in forward_output expired, and the main thread moved on.
+      // If this happened, the main thread closed our fd for us, so just return.
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc", "cmpxchg for thread %d failed", gettid());
+      return;
+    }
+
+    // Write our tid to the output fd to let the main thread know that we're working.
+    if (TEMP_FAILURE_RETRY(write(fd, &tid, sizeof(tid))) == sizeof(tid)) {
+      debuggerd_fallback_trace(fd, ucontext);
+    } else {
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to write to output fd");
+    }
+
+    close(fd);
     return;
   }
 
@@ -189,7 +247,14 @@
           return false;
         }
 
-        trace_output_fd.store(pipe_write.get());
+        uint64_t expected = pack_thread_fd(-1, -1);
+        if (!trace_output.compare_exchange_strong(expected,
+                                                  pack_thread_fd(tid, pipe_write.release()))) {
+          auto [tid, fd] = unpack_thread_fd(expected);
+          async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                                "thread %d is already outputting to fd %d?", tid, fd);
+          return false;
+        }
 
         siginfo_t siginfo = {};
         siginfo.si_code = SI_QUEUE;
@@ -203,12 +268,20 @@
           return false;
         }
 
-        bool success = forward_output(pipe_read.get(), output_fd);
-        if (success) {
-          // The signaled thread has closed trace_output_fd already.
-          (void)pipe_write.release();
-        } else {
-          trace_output_fd.store(-1);
+        bool success = forward_output(pipe_read.get(), output_fd, tid);
+        if (!success) {
+          async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                                "timeout expired while waiting for thread %d to dump", tid);
+        }
+
+        // Regardless of whether the poll succeeds, check to see if the thread took fd ownership.
+        uint64_t post_wait = trace_output.exchange(pack_thread_fd(-1, -1));
+        if (post_wait != pack_thread_fd(-1, -1)) {
+          auto [tid, fd] = unpack_thread_fd(post_wait);
+          if (fd != -1) {
+            async_safe_format_log(ANDROID_LOG_ERROR, "libc", "closing fd %d for thread %d", fd, tid);
+            close(fd);
+          }
         }
 
         return true;
diff --git a/debuggerd/seccomp_policy/crash_dump.arm.policy b/debuggerd/seccomp_policy/crash_dump.arm.policy
index c64e288..b1f459d 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm.policy
@@ -22,6 +22,7 @@
 process_vm_readv: 1
 tgkill: 1
 rt_sigprocmask: 1
+rt_sigaction: 1
 rt_tgsigqueueinfo: 1
 prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
 madvise: 1
@@ -30,7 +31,6 @@
 getuid32: 1
 fstat64: 1
 mmap2: arg2 in PROT_READ|PROT_WRITE
-sigaction: 1
 geteuid32: 1
 getgid32: 1
 getegid32: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.arm64.policy b/debuggerd/seccomp_policy/crash_dump.arm64.policy
index 0c689bb..e5e7afb 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm64.policy
@@ -21,6 +21,7 @@
 process_vm_readv: 1
 tgkill: 1
 rt_sigprocmask: 1
+rt_sigaction: 1
 rt_tgsigqueueinfo: 1
 prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
 madvise: 1
@@ -29,7 +30,6 @@
 getuid: 1
 fstat: 1
 mmap: arg2 in PROT_READ|PROT_WRITE
-rt_sigaction: 1
 geteuid: 1
 getgid: 1
 getegid: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.policy.def b/debuggerd/seccomp_policy/crash_dump.policy.def
index dadffac..b78c94a 100644
--- a/debuggerd/seccomp_policy/crash_dump.policy.def
+++ b/debuggerd/seccomp_policy/crash_dump.policy.def
@@ -29,6 +29,7 @@
 
 tgkill: 1
 rt_sigprocmask: 1
+rt_sigaction: 1
 rt_tgsigqueueinfo: 1
 
 #define PR_SET_VMA 0x53564d41
@@ -42,12 +43,10 @@
 getuid: 1
 fstat: 1
 mmap: arg2 in PROT_READ|PROT_WRITE
-rt_sigaction: 1
 #else
 getuid32: 1
 fstat64: 1
 mmap2: arg2 in PROT_READ|PROT_WRITE
-sigaction: 1
 #endif
 
 // Needed for logging.
diff --git a/debuggerd/seccomp_policy/crash_dump.x86.policy b/debuggerd/seccomp_policy/crash_dump.x86.policy
index c64e288..b1f459d 100644
--- a/debuggerd/seccomp_policy/crash_dump.x86.policy
+++ b/debuggerd/seccomp_policy/crash_dump.x86.policy
@@ -22,6 +22,7 @@
 process_vm_readv: 1
 tgkill: 1
 rt_sigprocmask: 1
+rt_sigaction: 1
 rt_tgsigqueueinfo: 1
 prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
 madvise: 1
@@ -30,7 +31,6 @@
 getuid32: 1
 fstat64: 1
 mmap2: arg2 in PROT_READ|PROT_WRITE
-sigaction: 1
 geteuid32: 1
 getgid32: 1
 getegid32: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.x86_64.policy b/debuggerd/seccomp_policy/crash_dump.x86_64.policy
index 0c689bb..e5e7afb 100644
--- a/debuggerd/seccomp_policy/crash_dump.x86_64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.x86_64.policy
@@ -21,6 +21,7 @@
 process_vm_readv: 1
 tgkill: 1
 rt_sigprocmask: 1
+rt_sigaction: 1
 rt_tgsigqueueinfo: 1
 prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
 madvise: 1
@@ -29,7 +30,6 @@
 getuid: 1
 fstat: 1
 mmap: arg2 in PROT_READ|PROT_WRITE
-rt_sigaction: 1
 geteuid: 1
 getgid: 1
 getegid: 1
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 676ee41..08b8b26 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -42,7 +42,6 @@
 #define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
 #define FAKE_BATTERY_CAPACITY 42
 #define FAKE_BATTERY_TEMPERATURE 424
-#define ALWAYS_PLUGGED_CAPACITY 100
 #define MILLION 1.0e6
 #define DEFAULT_VBUS_VOLTAGE 5000000
 
@@ -81,8 +80,11 @@
     props->batteryTechnology.clear();
 }
 
-BatteryMonitor::BatteryMonitor() : mHealthdConfig(nullptr), mBatteryDevicePresent(false),
-    mAlwaysPluggedDevice(false), mBatteryFixedCapacity(0), mBatteryFixedTemperature(0) {
+BatteryMonitor::BatteryMonitor()
+    : mHealthdConfig(nullptr),
+      mBatteryDevicePresent(false),
+      mBatteryFixedCapacity(0),
+      mBatteryFixedTemperature(0) {
     initBatteryProperties(&props);
 }
 
@@ -223,15 +225,6 @@
         mBatteryFixedTemperature :
         getIntField(mHealthdConfig->batteryTemperaturePath);
 
-    // For devices which do not have battery and are always plugged
-    // into power souce.
-    if (mAlwaysPluggedDevice) {
-        props.chargerAcOnline = true;
-        props.batteryPresent = true;
-        props.batteryStatus = BATTERY_STATUS_CHARGING;
-        props.batteryHealth = BATTERY_HEALTH_GOOD;
-    }
-
     std::string buf;
 
     if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
@@ -405,11 +398,7 @@
         break;
 
     case BATTERY_PROP_BATTERY_STATUS:
-        if (mAlwaysPluggedDevice) {
-            val->valueInt64 = BATTERY_STATUS_CHARGING;
-        } else {
-            val->valueInt64 = getChargeStatus();
-        }
+        val->valueInt64 = getChargeStatus();
         ret = NO_ERROR;
         break;
 
@@ -628,9 +617,6 @@
         KLOG_WARNING(LOG_TAG, "No battery devices found\n");
         hc->periodic_chores_interval_fast = -1;
         hc->periodic_chores_interval_slow = -1;
-        mBatteryFixedCapacity = ALWAYS_PLUGGED_CAPACITY;
-        mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
-        mAlwaysPluggedDevice = true;
     } else {
         if (mHealthdConfig->batteryStatusPath.isEmpty())
             KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
diff --git a/healthd/include/healthd/BatteryMonitor.h b/healthd/include/healthd/BatteryMonitor.h
index 8865a7d..194e667 100644
--- a/healthd/include/healthd/BatteryMonitor.h
+++ b/healthd/include/healthd/BatteryMonitor.h
@@ -48,7 +48,6 @@
     struct healthd_config *mHealthdConfig;
     Vector<String8> mChargerNames;
     bool mBatteryDevicePresent;
-    bool mAlwaysPluggedDevice;
     int mBatteryFixedCapacity;
     int mBatteryFixedTemperature;
     struct BatteryProperties props;
diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp
index 27255c2..4da8215 100644
--- a/libcutils/trace-dev.cpp
+++ b/libcutils/trace-dev.cpp
@@ -25,7 +25,6 @@
 void atrace_set_tracing_enabled(bool enabled)
 {
     atomic_store_explicit(&atrace_is_enabled, enabled, memory_order_release);
-    atomic_store_explicit(&atrace_is_ready, false, memory_order_release);
     atrace_update_tags();
 }
 
@@ -35,17 +34,18 @@
     if (atrace_marker_fd == -1) {
         ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno);
         atrace_enabled_tags = 0;
-        return;
+        goto done;
     }
+
     atrace_enabled_tags = atrace_get_property();
+
+done:
+    atomic_store_explicit(&atrace_is_ready, true, memory_order_release);
 }
 
 void atrace_setup()
 {
-    if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) {
-        pthread_once(&atrace_once_control, atrace_init_once);
-    }
-    atomic_store_explicit(&atrace_is_ready, true, memory_order_release);
+    pthread_once(&atrace_once_control, atrace_init_once);
 }
 
 void atrace_begin_body(const char* name)
diff --git a/libmemunreachable/PtracerThread.cpp b/libmemunreachable/PtracerThread.cpp
index aca2a82..61a1d24 100644
--- a/libmemunreachable/PtracerThread.cpp
+++ b/libmemunreachable/PtracerThread.cpp
@@ -98,6 +98,7 @@
     return (*reinterpret_cast<std::function<int()>*>(arg))();
   };
 
+  // See README.md for why we create the child process this way
   child_pid_ = clone(proxy, stack_->top(), CLONE_VM | CLONE_FS | CLONE_FILES /*|CLONE_UNTRACED*/,
                      reinterpret_cast<void*>(&func_));
   if (child_pid_ < 0) {
diff --git a/libmemunreachable/README.md b/libmemunreachable/README.md
index 61a47de..ae8fa94 100644
--- a/libmemunreachable/README.md
+++ b/libmemunreachable/README.md
@@ -36,7 +36,7 @@
 
  1. *Original process*: Leak detection is requested by calling `GetUnreachableMemory()`
  2. Allocations are disabled using `malloc_disable()`
- 3. The collection process is spawned.  The collection process is similar to a normal `fork()` child process, except that it shares the address space of the parent - any writes by the original process are visible to the collection process, and vice-versa.
+ 3. The collection process is spawned.  The collection process, created using clone, is similar to a normal `fork()` child process, except that it shares the address space of the parent - any writes by the original process are visible to the collection process, and vice-versa. If we forked instead of using clone, the address space might get out of sync with observed post-ptrace thread state, since it takes some time to pause the parent.
  4. *Collection process*: All threads in the original process are paused with `ptrace()`.
  5. Registers contents, active stack areas, and memory mapping information are collected.
  6. *Original process*: Allocations are re-enabled using `malloc_enable()`, but all threads are still paused with `ptrace()`.
diff --git a/libunwindstack/ArmExidx.cpp b/libunwindstack/ArmExidx.cpp
index 65638ae..6e397e3 100644
--- a/libunwindstack/ArmExidx.cpp
+++ b/libunwindstack/ArmExidx.cpp
@@ -22,12 +22,12 @@
 #include <android-base/stringprintf.h>
 
 #include <unwindstack/Log.h>
+#include <unwindstack/MachineArm.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsArm.h>
 
 #include "ArmExidx.h"
 #include "Check.h"
-#include "MachineArm.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index c2911df..b18b0ce 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -24,7 +24,7 @@
 
 #include <android-base/unique_fd.h>
 
-#include <dex/code_item_accessors-no_art-inl.h>
+#include <dex/code_item_accessors-inl.h>
 #include <dex/compact_dex_file.h>
 #include <dex/dex_file-inl.h>
 #include <dex/dex_file_loader.h>
diff --git a/libunwindstack/DwarfEhFrame.h b/libunwindstack/DwarfEhFrame.h
index 2589c89..7a41e45 100644
--- a/libunwindstack/DwarfEhFrame.h
+++ b/libunwindstack/DwarfEhFrame.h
@@ -46,4 +46,4 @@
 
 }  // namespace unwindstack
 
-#endif  // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
+#endif  // _LIBUNWINDSTACK_DWARF_EH_FRAME_H
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index 616d1b1..dfb8e8f 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -17,12 +17,12 @@
 #include <elf.h>
 #include <stdint.h>
 
+#include <unwindstack/MachineArm.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsArm.h>
 
 #include "ArmExidx.h"
 #include "ElfInterfaceArm.h"
-#include "MachineArm.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
index 7feafad..c7dec52 100644
--- a/libunwindstack/Regs.cpp
+++ b/libunwindstack/Regs.cpp
@@ -25,17 +25,16 @@
 #include <unwindstack/Regs.h>
 #include <unwindstack/RegsArm.h>
 #include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
 #include <unwindstack/RegsMips.h>
 #include <unwindstack/RegsMips64.h>
-
-#include "UserArm.h"
-#include "UserArm64.h"
-#include "UserX86.h"
-#include "UserX86_64.h"
-#include "UserMips.h"
-#include "UserMips64.h"
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
+#include <unwindstack/UserArm.h>
+#include <unwindstack/UserArm64.h>
+#include <unwindstack/UserMips.h>
+#include <unwindstack/UserMips64.h>
+#include <unwindstack/UserX86.h>
+#include <unwindstack/UserX86_64.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index d05c3e2..7f16146 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -19,13 +19,12 @@
 #include <functional>
 
 #include <unwindstack/Elf.h>
+#include <unwindstack/MachineArm.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsArm.h>
-
-#include "MachineArm.h"
-#include "UcontextArm.h"
-#include "UserArm.h"
+#include <unwindstack/UcontextArm.h>
+#include <unwindstack/UserArm.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index 2077bc5..d6b467a 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -19,13 +19,12 @@
 #include <functional>
 
 #include <unwindstack/Elf.h>
+#include <unwindstack/MachineArm64.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsArm64.h>
-
-#include "MachineArm64.h"
-#include "UcontextArm64.h"
-#include "UserArm64.h"
+#include <unwindstack/UcontextArm64.h>
+#include <unwindstack/UserArm64.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index 44cde05..6751f52 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -19,13 +19,12 @@
 #include <functional>
 
 #include <unwindstack/Elf.h>
+#include <unwindstack/MachineMips.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsMips.h>
-
-#include "MachineMips.h"
-#include "UcontextMips.h"
-#include "UserMips.h"
+#include <unwindstack/UcontextMips.h>
+#include <unwindstack/UserMips.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index b4e5246..97082bd 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -19,13 +19,12 @@
 #include <functional>
 
 #include <unwindstack/Elf.h>
+#include <unwindstack/MachineMips64.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsMips64.h>
-
-#include "MachineMips64.h"
-#include "UcontextMips64.h"
-#include "UserMips64.h"
+#include <unwindstack/UcontextMips64.h>
+#include <unwindstack/UserMips64.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index ef2f3de..27476b7 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -19,13 +19,12 @@
 #include <functional>
 
 #include <unwindstack/Elf.h>
+#include <unwindstack/MachineX86.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsX86.h>
-
-#include "MachineX86.h"
-#include "UcontextX86.h"
-#include "UserX86.h"
+#include <unwindstack/UcontextX86.h>
+#include <unwindstack/UserX86.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index 70921f8..0f66943 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -19,13 +19,12 @@
 #include <functional>
 
 #include <unwindstack/Elf.h>
+#include <unwindstack/MachineX86_64.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsX86_64.h>
-
-#include "MachineX86_64.h"
-#include "UcontextX86_64.h"
-#include "UserX86_64.h"
+#include <unwindstack/UcontextX86_64.h>
+#include <unwindstack/UserX86_64.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 6119ee0..dfd7b18 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -54,13 +54,18 @@
   frame->sp = regs_->sp();
 
   MapInfo* info = maps_->Find(dex_pc);
-  frame->map_start = info->start;
-  frame->map_end = info->end;
-  frame->map_offset = info->offset;
-  frame->map_load_bias = info->load_bias;
-  frame->map_flags = info->flags;
-  frame->map_name = info->name;
-  frame->rel_pc = dex_pc - info->start;
+  if (info != nullptr) {
+    frame->map_start = info->start;
+    frame->map_end = info->end;
+    frame->map_offset = info->offset;
+    frame->map_load_bias = info->load_bias;
+    frame->map_flags = info->flags;
+    frame->map_name = info->name;
+    frame->rel_pc = dex_pc - info->start;
+  } else {
+    frame->rel_pc = dex_pc;
+    return;
+  }
 
 #if !defined(NO_LIBDEXFILE_SUPPORT)
   if (dex_files_ == nullptr) {
@@ -170,6 +175,8 @@
       if (regs_->dex_pc() != 0) {
         // Add a frame to represent the dex file.
         FillInDexFrame();
+        // Clear the dex pc so that we don't repeat this frame later.
+        regs_->set_dex_pc(0);
       }
 
       FillInFrame(map_info, elf, adjusted_rel_pc, adjusted_pc);
diff --git a/libunwindstack/MachineArm.h b/libunwindstack/include/unwindstack/MachineArm.h
similarity index 100%
rename from libunwindstack/MachineArm.h
rename to libunwindstack/include/unwindstack/MachineArm.h
diff --git a/libunwindstack/MachineArm64.h b/libunwindstack/include/unwindstack/MachineArm64.h
similarity index 100%
rename from libunwindstack/MachineArm64.h
rename to libunwindstack/include/unwindstack/MachineArm64.h
diff --git a/libunwindstack/MachineMips.h b/libunwindstack/include/unwindstack/MachineMips.h
similarity index 100%
rename from libunwindstack/MachineMips.h
rename to libunwindstack/include/unwindstack/MachineMips.h
diff --git a/libunwindstack/MachineMips64.h b/libunwindstack/include/unwindstack/MachineMips64.h
similarity index 100%
rename from libunwindstack/MachineMips64.h
rename to libunwindstack/include/unwindstack/MachineMips64.h
diff --git a/libunwindstack/MachineX86.h b/libunwindstack/include/unwindstack/MachineX86.h
similarity index 100%
rename from libunwindstack/MachineX86.h
rename to libunwindstack/include/unwindstack/MachineX86.h
diff --git a/libunwindstack/MachineX86_64.h b/libunwindstack/include/unwindstack/MachineX86_64.h
similarity index 100%
rename from libunwindstack/MachineX86_64.h
rename to libunwindstack/include/unwindstack/MachineX86_64.h
diff --git a/libunwindstack/UcontextArm.h b/libunwindstack/include/unwindstack/UcontextArm.h
similarity index 98%
rename from libunwindstack/UcontextArm.h
rename to libunwindstack/include/unwindstack/UcontextArm.h
index 8c94166..7d1ec3b 100644
--- a/libunwindstack/UcontextArm.h
+++ b/libunwindstack/include/unwindstack/UcontextArm.h
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-#include "MachineArm.h"
+#include <unwindstack/MachineArm.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/UcontextArm64.h b/libunwindstack/include/unwindstack/UcontextArm64.h
similarity index 98%
rename from libunwindstack/UcontextArm64.h
rename to libunwindstack/include/unwindstack/UcontextArm64.h
index 655719f..a68be3b 100644
--- a/libunwindstack/UcontextArm64.h
+++ b/libunwindstack/include/unwindstack/UcontextArm64.h
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-#include "MachineArm64.h"
+#include <unwindstack/MachineArm64.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/UcontextMips.h b/libunwindstack/include/unwindstack/UcontextMips.h
similarity index 97%
rename from libunwindstack/UcontextMips.h
rename to libunwindstack/include/unwindstack/UcontextMips.h
index 27185e7..02e33b6 100644
--- a/libunwindstack/UcontextMips.h
+++ b/libunwindstack/include/unwindstack/UcontextMips.h
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-#include "MachineMips.h"
+#include <unwindstack/MachineMips.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/UcontextMips64.h b/libunwindstack/include/unwindstack/UcontextMips64.h
similarity index 96%
rename from libunwindstack/UcontextMips64.h
rename to libunwindstack/include/unwindstack/UcontextMips64.h
index 623bf3a..5b92a55 100644
--- a/libunwindstack/UcontextMips64.h
+++ b/libunwindstack/include/unwindstack/UcontextMips64.h
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-#include "MachineMips64.h"
+#include <unwindstack/MachineMips64.h>
 
 namespace unwindstack {
 
@@ -66,4 +66,4 @@
 
 }  // namespace unwindstack
 
-#endif  // _LIBUNWINDSTACK_UCONTEXT_MIPS6464_H
+#endif  // _LIBUNWINDSTACK_UCONTEXT_MIPS64_H
diff --git a/libunwindstack/UcontextX86.h b/libunwindstack/include/unwindstack/UcontextX86.h
similarity index 98%
rename from libunwindstack/UcontextX86.h
rename to libunwindstack/include/unwindstack/UcontextX86.h
index f79d92b..c96ebb7 100644
--- a/libunwindstack/UcontextX86.h
+++ b/libunwindstack/include/unwindstack/UcontextX86.h
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-#include "MachineX86.h"
+#include <unwindstack/MachineX86.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/UcontextX86_64.h b/libunwindstack/include/unwindstack/UcontextX86_64.h
similarity index 98%
rename from libunwindstack/UcontextX86_64.h
rename to libunwindstack/include/unwindstack/UcontextX86_64.h
index 2b8bdc4..4e163e5 100644
--- a/libunwindstack/UcontextX86_64.h
+++ b/libunwindstack/include/unwindstack/UcontextX86_64.h
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-#include "MachineX86_64.h"
+#include <unwindstack/MachineX86_64.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index e8af8b4..ebe7b0a 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -45,14 +45,14 @@
   uint64_t sp;
 
   std::string function_name;
-  uint64_t function_offset;
+  uint64_t function_offset = 0;
 
   std::string map_name;
-  uint64_t map_offset;
-  uint64_t map_start;
-  uint64_t map_end;
-  uint64_t map_load_bias;
-  int map_flags;
+  uint64_t map_offset = 0;
+  uint64_t map_start = 0;
+  uint64_t map_end = 0;
+  uint64_t map_load_bias = 0;
+  int map_flags = 0;
 };
 
 class Unwinder {
diff --git a/libunwindstack/UserArm.h b/libunwindstack/include/unwindstack/UserArm.h
similarity index 100%
rename from libunwindstack/UserArm.h
rename to libunwindstack/include/unwindstack/UserArm.h
diff --git a/libunwindstack/UserArm64.h b/libunwindstack/include/unwindstack/UserArm64.h
similarity index 100%
rename from libunwindstack/UserArm64.h
rename to libunwindstack/include/unwindstack/UserArm64.h
diff --git a/libunwindstack/UserMips.h b/libunwindstack/include/unwindstack/UserMips.h
similarity index 100%
rename from libunwindstack/UserMips.h
rename to libunwindstack/include/unwindstack/UserMips.h
diff --git a/libunwindstack/UserMips64.h b/libunwindstack/include/unwindstack/UserMips64.h
similarity index 100%
rename from libunwindstack/UserMips64.h
rename to libunwindstack/include/unwindstack/UserMips64.h
diff --git a/libunwindstack/UserX86.h b/libunwindstack/include/unwindstack/UserX86.h
similarity index 100%
rename from libunwindstack/UserX86.h
rename to libunwindstack/include/unwindstack/UserX86.h
diff --git a/libunwindstack/UserX86_64.h b/libunwindstack/include/unwindstack/UserX86_64.h
similarity index 100%
rename from libunwindstack/UserX86_64.h
rename to libunwindstack/include/unwindstack/UserX86_64.h
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 6e05c5e..0b02c5b 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -25,7 +25,7 @@
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 
-#include <dex/code_item_accessors-no_art-inl.h>
+#include <dex/code_item_accessors-inl.h>
 #include <dex/standard_dex_file.h>
 
 #include <gtest/gtest.h>
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index 31d6a63..70a52ad 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -20,10 +20,10 @@
 
 #include <vector>
 
+#include <unwindstack/MachineArm.h>
 #include <unwindstack/RegsArm.h>
 
 #include "ElfInterfaceArm.h"
-#include "MachineArm.h"
 
 #include "ElfFake.h"
 #include "MemoryFake.h"
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index 8f7d913..cd7f2ff 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -56,6 +56,7 @@
   void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; }
   void FakeSetPc(uint64_t pc) { fake_pc_ = pc; }
   void FakeSetSp(uint64_t sp) { fake_sp_ = sp; }
+  void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
   void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
   void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
 
diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp
index 8b5b31f..9a27dbd 100644
--- a/libunwindstack/tests/RegsIterateTest.cpp
+++ b/libunwindstack/tests/RegsIterateTest.cpp
@@ -24,20 +24,19 @@
 
 #include <unwindstack/Elf.h>
 #include <unwindstack/ElfInterface.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/MachineMips.h>
+#include <unwindstack/MachineMips64.h>
+#include <unwindstack/MachineX86.h>
+#include <unwindstack/MachineX86_64.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/RegsArm.h>
 #include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
 #include <unwindstack/RegsMips.h>
 #include <unwindstack/RegsMips64.h>
-
-#include "MachineArm.h"
-#include "MachineArm64.h"
-#include "MachineX86.h"
-#include "MachineX86_64.h"
-#include "MachineMips.h"
-#include "MachineMips64.h"
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
index ef9e61c..ecd4051 100644
--- a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
+++ b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
@@ -19,19 +19,18 @@
 #include <gtest/gtest.h>
 
 #include <unwindstack/Elf.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/MachineMips.h>
+#include <unwindstack/MachineMips64.h>
+#include <unwindstack/MachineX86.h>
+#include <unwindstack/MachineX86_64.h>
 #include <unwindstack/RegsArm.h>
 #include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
 #include <unwindstack/RegsMips.h>
 #include <unwindstack/RegsMips64.h>
-
-#include "MachineArm.h"
-#include "MachineArm64.h"
-#include "MachineX86.h"
-#include "MachineX86_64.h"
-#include "MachineMips.h"
-#include "MachineMips64.h"
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
 
 #include "MemoryFake.h"
 
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index e93d826..e499593 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -26,6 +26,9 @@
 #include <vector>
 
 #include <unwindstack/JitDebug.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/MachineX86.h>
 #include <unwindstack/Maps.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/RegsArm.h>
@@ -33,10 +36,6 @@
 #include <unwindstack/RegsX86.h>
 #include <unwindstack/Unwinder.h>
 
-#include "MachineArm.h"
-#include "MachineArm64.h"
-#include "MachineX86.h"
-
 #include "ElfTestUtils.h"
 
 namespace unwindstack {
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 45cf907..7358ae6 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -98,6 +98,10 @@
     info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
     maps_.FakeAddMapInfo(info);
 
+    info = new MapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
+    info->load_bias = 0;
+    maps_.FakeAddMapInfo(info);
+
     process_memory_.reset(new MemoryFake);
   }
 
@@ -666,6 +670,146 @@
   EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
+TEST_F(UnwinderTest, dex_pc_in_map) {
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+  regs_.FakeSetPc(0x1000);
+  regs_.FakeSetSp(0x10000);
+  regs_.FakeSetDexPc(0xa3400);
+
+  Unwinder unwinder(64, &maps_, &regs_, process_memory_);
+  unwinder.Unwind();
+  EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+
+  ASSERT_EQ(2U, unwinder.NumFrames());
+
+  auto* frame = &unwinder.frames()[0];
+  EXPECT_EQ(0U, frame->num);
+  EXPECT_EQ(0x400U, frame->rel_pc);
+  EXPECT_EQ(0xa3400U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/fake/fake.vdex", frame->map_name);
+  EXPECT_EQ(0U, frame->map_offset);
+  EXPECT_EQ(0xa3000U, frame->map_start);
+  EXPECT_EQ(0xa4000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+
+  frame = &unwinder.frames()[1];
+  EXPECT_EQ(1U, frame->num);
+  EXPECT_EQ(0U, frame->rel_pc);
+  EXPECT_EQ(0x1000U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("Frame0", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+}
+
+TEST_F(UnwinderTest, dex_pc_not_in_map) {
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+  regs_.FakeSetPc(0x1000);
+  regs_.FakeSetSp(0x10000);
+  regs_.FakeSetDexPc(0x50000);
+
+  Unwinder unwinder(64, &maps_, &regs_, process_memory_);
+  unwinder.Unwind();
+  EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+
+  ASSERT_EQ(2U, unwinder.NumFrames());
+
+  auto* frame = &unwinder.frames()[0];
+  EXPECT_EQ(0U, frame->num);
+  EXPECT_EQ(0x50000U, frame->rel_pc);
+  EXPECT_EQ(0x50000U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_offset);
+  EXPECT_EQ(0U, frame->map_start);
+  EXPECT_EQ(0U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(0, frame->map_flags);
+
+  frame = &unwinder.frames()[1];
+  EXPECT_EQ(1U, frame->num);
+  EXPECT_EQ(0U, frame->rel_pc);
+  EXPECT_EQ(0x1000U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("Frame0", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+}
+
+TEST_F(UnwinderTest, dex_pc_multiple_frames) {
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
+  regs_.FakeSetPc(0x1000);
+  regs_.FakeSetSp(0x10000);
+  regs_.FakeSetDexPc(0xa3400);
+  ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
+  ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+  Unwinder unwinder(64, &maps_, &regs_, process_memory_);
+  unwinder.Unwind();
+  EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+
+  ASSERT_EQ(3U, unwinder.NumFrames());
+
+  auto* frame = &unwinder.frames()[0];
+  EXPECT_EQ(0U, frame->num);
+  EXPECT_EQ(0x400U, frame->rel_pc);
+  EXPECT_EQ(0xa3400U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/fake/fake.vdex", frame->map_name);
+  EXPECT_EQ(0U, frame->map_offset);
+  EXPECT_EQ(0xa3000U, frame->map_start);
+  EXPECT_EQ(0xa4000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+
+  frame = &unwinder.frames()[1];
+  EXPECT_EQ(1U, frame->num);
+  EXPECT_EQ(0U, frame->rel_pc);
+  EXPECT_EQ(0x1000U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("Frame0", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+
+  frame = &unwinder.frames()[2];
+  EXPECT_EQ(2U, frame->num);
+  EXPECT_EQ(0x400U, frame->rel_pc);
+  EXPECT_EQ(0x33400U, frame->pc);
+  EXPECT_EQ(0x10010U, frame->sp);
+  EXPECT_EQ("Frame1", frame->function_name);
+  EXPECT_EQ(1U, frame->function_offset);
+  EXPECT_EQ("/fake/compressed.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_offset);
+  EXPECT_EQ(0x33000U, frame->map_start);
+  EXPECT_EQ(0x34000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+}
+
 // Verify format frame code.
 TEST_F(UnwinderTest, format_frame_static) {
   FrameData frame;
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index b486a17..15471e0 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -615,11 +615,11 @@
     pid_remove(pid);
 
     if (r) {
-        ALOGE("kill(%d): errno=%d", procp->pid, errno);
+        ALOGE("kill(%d): errno=%d", pid, errno);
         return -1;
-    } else {
-        return tasksize;
     }
+
+    return tasksize;
 }
 
 /*
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index d8163ab..f4509a4 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -192,11 +192,12 @@
 # ld.config.txt
 #
 # For VNDK enforced devices that have defined BOARD_VNDK_VERSION, use
-# "ld.config.txt.in" as a source file. This configuration includes strict VNDK
+# "ld.config.txt" as a source file. This configuration includes strict VNDK
 # run-time restrictions for vendor process.
 # Other treblized devices, that have not defined BOARD_VNDK_VERSION or that
-# have set BOARD_VNDK_RUNTIME_DISABLE to true, use "ld.config.txt" as a source
-# file. This configuration does not have strict VNDK run-time restrictions.
+# have set BOARD_VNDK_RUNTIME_DISABLE to true, use "ld.config.vndk_lite.txt"
+# as a source file. This configuration does not have strict VNDK run-time
+# restrictions.
 # If the device is not treblized, use "ld.config.legacy.txt" for legacy
 # namespace configuration.
 include $(CLEAR_VARS)
@@ -216,7 +217,7 @@
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
 $(eval $(call update_and_install_ld_config,\
-  $(LOCAL_PATH)/etc/ld.config.txt.in,\
+  $(LOCAL_PATH)/etc/ld.config.txt,\
   $(LOCAL_BUILT_MODULE),\
   $(PLATFORM_VNDK_VERSION)))
 
@@ -225,7 +226,7 @@
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
 $(eval $(call update_and_install_ld_config,\
-  $(LOCAL_PATH)/etc/ld.config.txt,\
+  $(LOCAL_PATH)/etc/ld.config.vndk_lite.txt,\
   $(LOCAL_BUILT_MODULE),\
   $(if $(BOARD_VNDK_VERSION),$(PLATFORM_VNDK_VERSION))))
 
@@ -244,9 +245,9 @@
 #
 # This file is a temporary configuration file only for GSI. Originally GSI has
 # BOARD_VNDK_VERSION defined and has strict VNDK enforcing rule based on
-# "ld.config.txt.in". However for the devices, that have not defined
+# "ld.config.txt". However for the devices, that have not defined
 # BOARD_VNDK_VERSION, GSI provides this configuration file which is based on
-# "ld.config.txt".
+# "ld.config.vndk_lite.txt".
 # Do not install this file for the devices other than GSI.
 include $(CLEAR_VARS)
 LOCAL_MODULE := ld.config.noenforce.txt
@@ -255,7 +256,7 @@
 LOCAL_MODULE_STEM := $(LOCAL_MODULE)
 include $(BUILD_SYSTEM)/base_rules.mk
 $(eval $(call update_and_install_ld_config,\
-  $(LOCAL_PATH)/etc/ld.config.txt,\
+  $(LOCAL_PATH)/etc/ld.config.vndk_lite.txt,\
   $(LOCAL_BUILT_MODULE),\
   $(PLATFORM_VNDK_VERSION)))
 
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 5d97a73..c8d87c8 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -30,21 +30,55 @@
 ###############################################################################
 # "default" namespace
 #
-# Framework-side code runs in this namespace. However, libs from other
-# partitions are also allowed temporarily.
+# Framework-side code runs in this namespace. Libs from /vendor partition
+# can't be loaded in this namespace.
 ###############################################################################
-namespace.default.isolated = false
+namespace.default.isolated = true
 
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /odm/${LIB}
-namespace.default.search.paths += /vendor/${LIB}
+namespace.default.search.paths = /system/${LIB}
+
+# We can't have entire /system/${LIB} as permitted paths because doing so
+# makes it possible to load libs in /system/${LIB}/vndk* directories by
+# their absolute paths (e.g. dlopen("/system/lib/vndk/libbase.so");).
+# VNDK libs are built with previous versions of Android and thus must not be
+# loaded into this namespace where libs built with the current version of
+# Android are loaded. Mixing the two types of libs in the same namespace can
+# cause unexpected problem.
+namespace.default.permitted.paths  = /system/${LIB}/drm
+namespace.default.permitted.paths += /system/${LIB}/extractors
+namespace.default.permitted.paths += /system/${LIB}/hw
+# These are where odex files are located. libart has to be able to dlopen the files
+namespace.default.permitted.paths += /system/framework
+namespace.default.permitted.paths += /system/app
+namespace.default.permitted.paths += /system/priv-app
+namespace.default.permitted.paths += /vendor/framework
+namespace.default.permitted.paths += /vendor/app
+namespace.default.permitted.paths += /vendor/priv-app
+namespace.default.permitted.paths += /oem/app
+namespace.default.permitted.paths += /product/framework
+namespace.default.permitted.paths += /product/app
+namespace.default.permitted.paths += /product/priv-app
+namespace.default.permitted.paths += /data
+namespace.default.permitted.paths += /mnt/expand
 
 namespace.default.asan.search.paths  = /data/asan/system/${LIB}
 namespace.default.asan.search.paths +=           /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}
-namespace.default.asan.search.paths +=           /odm/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.default.asan.search.paths +=           /vendor/${LIB}
+
+namespace.default.asan.permitted.paths  = /data
+namespace.default.asan.permitted.paths += /system/${LIB}/drm
+namespace.default.asan.permitted.paths += /system/${LIB}/extractors
+namespace.default.asan.permitted.paths += /system/${LIB}/hw
+namespace.default.asan.permitted.paths += /system/framework
+namespace.default.asan.permitted.paths += /system/app
+namespace.default.asan.permitted.paths += /system/priv-app
+namespace.default.asan.permitted.paths += /vendor/framework
+namespace.default.asan.permitted.paths += /vendor/app
+namespace.default.asan.permitted.paths += /vendor/priv-app
+namespace.default.asan.permitted.paths += /oem/app
+namespace.default.asan.permitted.paths += /product/framework
+namespace.default.asan.permitted.paths += /product/app
+namespace.default.asan.permitted.paths += /product/priv-app
+namespace.default.asan.permitted.paths += /mnt/expand
 
 ###############################################################################
 # "sphal" namespace
@@ -82,35 +116,10 @@
 # libs listed here can be used.
 namespace.sphal.links = default,vndk,rs
 
-# WARNING: only NDK libs can be listed here.
-namespace.sphal.link.default.shared_libs  = libc.so
-namespace.sphal.link.default.shared_libs += libEGL.so
-namespace.sphal.link.default.shared_libs += libGLESv1_CM.so
-namespace.sphal.link.default.shared_libs += libGLESv2.so
-namespace.sphal.link.default.shared_libs += libdl.so
-namespace.sphal.link.default.shared_libs += liblog.so
-namespace.sphal.link.default.shared_libs += libm.so
-namespace.sphal.link.default.shared_libs += libnativewindow.so
-namespace.sphal.link.default.shared_libs += libstdc++.so
-namespace.sphal.link.default.shared_libs += libsync.so
-namespace.sphal.link.default.shared_libs += libvndksupport.so
-namespace.sphal.link.default.shared_libs += libz.so
+namespace.sphal.link.default.shared_libs  = %LLNDK_LIBRARIES%
+namespace.sphal.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
-# WARNING: only VNDK-SP libs can be listed here. DO NOT EDIT this line.
-namespace.sphal.link.vndk.shared_libs  = android.hardware.renderscript@1.0.so
-namespace.sphal.link.vndk.shared_libs += android.hardware.graphics.common@1.0.so
-namespace.sphal.link.vndk.shared_libs += android.hardware.graphics.mapper@2.0.so
-namespace.sphal.link.vndk.shared_libs += android.hidl.memory@1.0.so
-namespace.sphal.link.vndk.shared_libs += libbase.so
-namespace.sphal.link.vndk.shared_libs += libc++.so
-namespace.sphal.link.vndk.shared_libs += libcutils.so
-namespace.sphal.link.vndk.shared_libs += libhardware.so
-namespace.sphal.link.vndk.shared_libs += libhidlbase.so
-namespace.sphal.link.vndk.shared_libs += libhidlmemory.so
-namespace.sphal.link.vndk.shared_libs += libhidltransport.so
-namespace.sphal.link.vndk.shared_libs += libhwbinder.so
-namespace.sphal.link.vndk.shared_libs += libion.so
-namespace.sphal.link.vndk.shared_libs += libutils.so
+namespace.sphal.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
 
 # Renderscript gets separate namespace
 namespace.sphal.link.rs.shared_libs = libRS_internal.so
@@ -155,38 +164,13 @@
 
 namespace.rs.links = default,vndk
 
-namespace.rs.link.default.shared_libs  = libc.so
-namespace.rs.link.default.shared_libs += libEGL.so
-namespace.rs.link.default.shared_libs += libGLESv1_CM.so
-namespace.rs.link.default.shared_libs += libGLESv2.so
-namespace.rs.link.default.shared_libs += libdl.so
-namespace.rs.link.default.shared_libs += liblog.so
-namespace.rs.link.default.shared_libs += libm.so
-namespace.rs.link.default.shared_libs += libnativewindow.so
-namespace.rs.link.default.shared_libs += libstdc++.so
-namespace.rs.link.default.shared_libs += libsync.so
-namespace.rs.link.default.shared_libs += libvndksupport.so
-namespace.rs.link.default.shared_libs += libz.so
-# These two libs are private LLNDK libs but are exceptionally visible
-# in this 'rs' namespace because RenderScript framework libraries
-# which are loaded into this namespace are using them.
-namespace.rs.link.default.shared_libs += libft2.so
-namespace.rs.link.default.shared_libs += libmediandk.so
+namespace.rs.link.default.shared_libs  =  %LLNDK_LIBRARIES%
+namespace.rs.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+# Private LLNDK libs (e.g. libft2.so) are exceptionally allowed to this
+# namespace because RS framework libs are using them.
+namespace.rs.link.default.shared_libs += %PRIVATE_LLNDK_LIBRARIES%
 
-namespace.rs.link.vndk.shared_libs  = android.hardware.renderscript@1.0.so
-namespace.rs.link.vndk.shared_libs += android.hardware.graphics.common@1.0.so
-namespace.rs.link.vndk.shared_libs += android.hardware.graphics.mapper@2.0.so
-namespace.rs.link.vndk.shared_libs += android.hidl.memory@1.0.so
-namespace.rs.link.vndk.shared_libs += libbase.so
-namespace.rs.link.vndk.shared_libs += libc++.so
-namespace.rs.link.vndk.shared_libs += libcutils.so
-namespace.rs.link.vndk.shared_libs += libhardware.so
-namespace.rs.link.vndk.shared_libs += libhidlbase.so
-namespace.rs.link.vndk.shared_libs += libhidlmemory.so
-namespace.rs.link.vndk.shared_libs += libhidltransport.so
-namespace.rs.link.vndk.shared_libs += libhwbinder.so
-namespace.rs.link.vndk.shared_libs += libion.so
-namespace.rs.link.vndk.shared_libs += libutils.so
+namespace.rs.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
 
 ###############################################################################
 # "vndk" namespace
@@ -204,6 +188,8 @@
 namespace.vndk.permitted.paths += /odm/${LIB}/egl
 namespace.vndk.permitted.paths += /vendor/${LIB}/hw
 namespace.vndk.permitted.paths += /vendor/${LIB}/egl
+# This is exceptionally required since android.hidl.memory@1.0-impl.so is here
+namespace.vndk.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER%/hw
 
 namespace.vndk.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
 namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk-sp
@@ -221,21 +207,15 @@
 namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/egl
 namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/egl
 
+namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
+namespace.vndk.asan.permitted.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%/hw
+
 # When these NDK libs are required inside this namespace, then it is redirected
 # to the default namespace. This is possible since their ABI is stable across
 # Android releases.
 namespace.vndk.links = default
-namespace.vndk.link.default.shared_libs  = android.hidl.memory@1.0-impl.so
-namespace.vndk.link.default.shared_libs += libEGL.so
-namespace.vndk.link.default.shared_libs += libc.so
-namespace.vndk.link.default.shared_libs += libdl.so
-namespace.vndk.link.default.shared_libs += liblog.so
-namespace.vndk.link.default.shared_libs += libm.so
-namespace.vndk.link.default.shared_libs += libnativewindow.so
-namespace.vndk.link.default.shared_libs += libstdc++.so
-namespace.vndk.link.default.shared_libs += libsync.so
-namespace.vndk.link.default.shared_libs += libvndksupport.so
-namespace.vndk.link.default.shared_libs += libz.so
+namespace.vndk.link.default.shared_libs  = %LLNDK_LIBRARIES%
+namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
 ###############################################################################
 # Namespace config for vendor processes. In O, no restriction is enforced for
@@ -244,35 +224,88 @@
 # (LL-NDK only) access.
 ###############################################################################
 [vendor]
-namespace.default.isolated = false
+additional.namespaces = system,vndk
+
+###############################################################################
+# "default" namespace
+#
+# This is the default linker namespace for a vendor process (a process started
+# from /vendor/bin/*). The main executable and the libs under /vendor/lib[64]
+# are loaded directly into this namespace. However, other libs under the system
+# partition (VNDK and LLNDK libraries) are not loaded here but from the
+# separate namespace 'system'. The delegation to the system namespace is done
+# via the 'namespace.default.link.system.shared_libs' property below.
+###############################################################################
+namespace.default.isolated = true
+namespace.default.visible = true
 
 namespace.default.search.paths  = /odm/${LIB}
-namespace.default.search.paths += /odm/${LIB}/vndk
-namespace.default.search.paths += /odm/${LIB}/vndk-sp
 namespace.default.search.paths += /vendor/${LIB}
-namespace.default.search.paths += /vendor/${LIB}/vndk
-namespace.default.search.paths += /vendor/${LIB}/vndk-sp
 
-# Access to system libraries are allowed
-namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
-namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.default.search.paths += /system/${LIB}
+namespace.default.permitted.paths  = /odm
+namespace.default.permitted.paths += /vendor
 
 namespace.default.asan.search.paths  = /data/asan/odm/${LIB}
 namespace.default.asan.search.paths +=           /odm/${LIB}
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}/vndk
-namespace.default.asan.search.paths +=           /odm/${LIB}/vndk
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}/vndk-sp
-namespace.default.asan.search.paths +=           /odm/${LIB}/vndk-sp
 namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
 namespace.default.asan.search.paths +=           /vendor/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/vndk
-namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
-namespace.default.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
-namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.default.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.default.asan.search.paths += /data/asan/system/${LIB}
-namespace.default.asan.search.paths +=           /system/${LIB}
+
+namespace.default.asan.permitted.paths  = /data/asan/odm
+namespace.default.asan.permitted.paths +=           /odm
+namespace.default.asan.permitted.paths += /data/asan/vendor
+namespace.default.asan.permitted.paths +=           /vendor
+
+namespace.default.links = system,vndk
+namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES%
+namespace.default.link.vndk.shared_libs  = %VNDK_SAMEPROCESS_LIBRARIES%
+namespace.default.link.vndk.shared_libs += %VNDK_CORE_LIBRARIES%
+
+###############################################################################
+# "vndk" namespace
+#
+# This namespace is where VNDK and VNDK-SP libraries are loaded for
+# a vendor process.
+###############################################################################
+namespace.vndk.isolated = false
+
+namespace.vndk.search.paths  = /odm/${LIB}/vndk
+namespace.vndk.search.paths += /odm/${LIB}/vndk-sp
+namespace.vndk.search.paths += /vendor/${LIB}/vndk
+namespace.vndk.search.paths += /vendor/${LIB}/vndk-sp
+namespace.vndk.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
+namespace.vndk.search.paths += /system/${LIB}/vndk%VNDK_VER%
+
+namespace.vndk.asan.search.paths  = /data/asan/odm/${LIB}/vndk
+namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk
+namespace.vndk.asan.search.paths += /data/asan/odm/${LIB}/vndk-sp
+namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk-sp
+namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk
+namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk
+namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
+namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk-sp
+namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
+namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
+namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
+namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
+
+# When these NDK libs are required inside this namespace, then it is redirected
+# to the system namespace. This is possible since their ABI is stable across
+# Android releases.
+namespace.vndk.links = system,default
+namespace.vndk.link.system.shared_libs  = %LLNDK_LIBRARIES%
+namespace.vndk.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
+namespace.vndk.link.default.allow_all_shared_libs = true
+
+###############################################################################
+# "system" namespace
+#
+# This namespace is where system libs (VNDK and LLNDK libs) are loaded for
+# a vendor process.
+###############################################################################
+namespace.system.isolated = false
+
+namespace.system.search.paths = /system/${LIB}
+
+namespace.system.asan.search.paths  = /data/asan/system/${LIB}
+namespace.system.asan.search.paths +=           /system/${LIB}
diff --git a/rootdir/etc/ld.config.txt.in b/rootdir/etc/ld.config.txt.in
deleted file mode 100644
index c8d87c8..0000000
--- a/rootdir/etc/ld.config.txt.in
+++ /dev/null
@@ -1,311 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Bionic loader config file.
-#
-
-# Don't change the order here. The first pattern that matches with the
-# absolute path of an executable is selected.
-dir.system = /system/bin/
-dir.system = /system/xbin/
-
-dir.vendor = /odm/bin/
-dir.vendor = /vendor/bin/
-dir.vendor = /data/nativetest/odm
-dir.vendor = /data/nativetest64/odm
-dir.vendor = /data/benchmarktest/odm
-dir.vendor = /data/benchmarktest64/odm
-dir.vendor = /data/nativetest/vendor
-dir.vendor = /data/nativetest64/vendor
-dir.vendor = /data/benchmarktest/vendor
-dir.vendor = /data/benchmarktest64/vendor
-
-dir.system = /data/nativetest
-dir.system = /data/nativetest64
-dir.system = /data/benchmarktest
-dir.system = /data/benchmarktest64
-
-[system]
-additional.namespaces = sphal,vndk,rs
-
-###############################################################################
-# "default" namespace
-#
-# Framework-side code runs in this namespace. Libs from /vendor partition
-# can't be loaded in this namespace.
-###############################################################################
-namespace.default.isolated = true
-
-namespace.default.search.paths = /system/${LIB}
-
-# We can't have entire /system/${LIB} as permitted paths because doing so
-# makes it possible to load libs in /system/${LIB}/vndk* directories by
-# their absolute paths (e.g. dlopen("/system/lib/vndk/libbase.so");).
-# VNDK libs are built with previous versions of Android and thus must not be
-# loaded into this namespace where libs built with the current version of
-# Android are loaded. Mixing the two types of libs in the same namespace can
-# cause unexpected problem.
-namespace.default.permitted.paths  = /system/${LIB}/drm
-namespace.default.permitted.paths += /system/${LIB}/extractors
-namespace.default.permitted.paths += /system/${LIB}/hw
-# These are where odex files are located. libart has to be able to dlopen the files
-namespace.default.permitted.paths += /system/framework
-namespace.default.permitted.paths += /system/app
-namespace.default.permitted.paths += /system/priv-app
-namespace.default.permitted.paths += /vendor/framework
-namespace.default.permitted.paths += /vendor/app
-namespace.default.permitted.paths += /vendor/priv-app
-namespace.default.permitted.paths += /oem/app
-namespace.default.permitted.paths += /product/framework
-namespace.default.permitted.paths += /product/app
-namespace.default.permitted.paths += /product/priv-app
-namespace.default.permitted.paths += /data
-namespace.default.permitted.paths += /mnt/expand
-
-namespace.default.asan.search.paths  = /data/asan/system/${LIB}
-namespace.default.asan.search.paths +=           /system/${LIB}
-
-namespace.default.asan.permitted.paths  = /data
-namespace.default.asan.permitted.paths += /system/${LIB}/drm
-namespace.default.asan.permitted.paths += /system/${LIB}/extractors
-namespace.default.asan.permitted.paths += /system/${LIB}/hw
-namespace.default.asan.permitted.paths += /system/framework
-namespace.default.asan.permitted.paths += /system/app
-namespace.default.asan.permitted.paths += /system/priv-app
-namespace.default.asan.permitted.paths += /vendor/framework
-namespace.default.asan.permitted.paths += /vendor/app
-namespace.default.asan.permitted.paths += /vendor/priv-app
-namespace.default.asan.permitted.paths += /oem/app
-namespace.default.asan.permitted.paths += /product/framework
-namespace.default.asan.permitted.paths += /product/app
-namespace.default.asan.permitted.paths += /product/priv-app
-namespace.default.asan.permitted.paths += /mnt/expand
-
-###############################################################################
-# "sphal" namespace
-#
-# SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
-# loaded inside system processes. libEGL_<chipset>.so, libGLESv2_<chipset>.so,
-# android.hardware.graphics.mapper@2.0-impl.so, etc are SP-HALs.
-#
-# This namespace is exclusivly for SP-HALs. When the framework tries to dynami-
-# cally load SP-HALs, android_dlopen_ext() is used to explicitly specifying
-# that they should be searched and loaded from this namespace.
-#
-# Note that there is no link from the default namespace to this namespace.
-###############################################################################
-namespace.sphal.isolated = true
-namespace.sphal.visible = true
-
-namespace.sphal.search.paths  = /odm/${LIB}
-namespace.sphal.search.paths += /vendor/${LIB}
-
-namespace.sphal.permitted.paths  = /odm/${LIB}
-namespace.sphal.permitted.paths += /vendor/${LIB}
-
-namespace.sphal.asan.search.paths  = /data/asan/odm/${LIB}
-namespace.sphal.asan.search.paths +=           /odm/${LIB}
-namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.sphal.asan.search.paths +=           /vendor/${LIB}
-
-namespace.sphal.asan.permitted.paths  = /data/asan/odm/${LIB}
-namespace.sphal.asan.permitted.paths +=           /odm/${LIB}
-namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}
-namespace.sphal.asan.permitted.paths +=           /vendor/${LIB}
-
-# Once in this namespace, access to libraries in /system/lib is restricted. Only
-# libs listed here can be used.
-namespace.sphal.links = default,vndk,rs
-
-namespace.sphal.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.sphal.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.sphal.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
-
-# Renderscript gets separate namespace
-namespace.sphal.link.rs.shared_libs = libRS_internal.so
-
-###############################################################################
-# "rs" namespace
-#
-# This namespace is exclusively for Renderscript internal libraries.
-# This namespace has slightly looser restriction than the vndk namespace because
-# of the genuine characteristics of Renderscript; /data is in the permitted path
-# to load the compiled *.so file and libmediandk.so can be used here.
-###############################################################################
-namespace.rs.isolated = true
-namespace.rs.visible = true
-
-namespace.rs.search.paths  = /odm/${LIB}/vndk-sp
-namespace.rs.search.paths += /vendor/${LIB}/vndk-sp
-namespace.rs.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.search.paths += /odm/${LIB}
-namespace.rs.search.paths += /vendor/${LIB}
-
-namespace.rs.permitted.paths  = /odm/${LIB}
-namespace.rs.permitted.paths += /vendor/${LIB}
-namespace.rs.permitted.paths += /data
-
-namespace.rs.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
-namespace.rs.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.rs.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.rs.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.rs.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.asan.search.paths += /data/asan/odm/${LIB}
-namespace.rs.asan.search.paths +=           /odm/${LIB}
-namespace.rs.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.rs.asan.search.paths +=           /vendor/${LIB}
-
-namespace.rs.asan.permitted.paths  = /data/asan/odm/${LIB}
-namespace.rs.asan.permitted.paths +=           /odm/${LIB}
-namespace.rs.asan.permitted.paths += /data/asan/vendor/${LIB}
-namespace.rs.asan.permitted.paths +=           /vendor/${LIB}
-namespace.rs.asan.permitted.paths += /data
-
-namespace.rs.links = default,vndk
-
-namespace.rs.link.default.shared_libs  =  %LLNDK_LIBRARIES%
-namespace.rs.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-# Private LLNDK libs (e.g. libft2.so) are exceptionally allowed to this
-# namespace because RS framework libs are using them.
-namespace.rs.link.default.shared_libs += %PRIVATE_LLNDK_LIBRARIES%
-
-namespace.rs.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
-
-###############################################################################
-# "vndk" namespace
-#
-# This namespace is exclusively for vndk-sp libs.
-###############################################################################
-namespace.vndk.isolated = true
-namespace.vndk.visible = true
-
-namespace.vndk.search.paths  = /odm/${LIB}/vndk-sp
-namespace.vndk.search.paths += /vendor/${LIB}/vndk-sp
-namespace.vndk.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-
-namespace.vndk.permitted.paths  = /odm/${LIB}/hw
-namespace.vndk.permitted.paths += /odm/${LIB}/egl
-namespace.vndk.permitted.paths += /vendor/${LIB}/hw
-namespace.vndk.permitted.paths += /vendor/${LIB}/egl
-# This is exceptionally required since android.hidl.memory@1.0-impl.so is here
-namespace.vndk.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER%/hw
-
-namespace.vndk.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-
-namespace.vndk.asan.permitted.paths  = /data/asan/odm/${LIB}/hw
-namespace.vndk.asan.permitted.paths +=           /odm/${LIB}/hw
-namespace.vndk.asan.permitted.paths += /data/asan/odm/${LIB}/egl
-namespace.vndk.asan.permitted.paths +=           /odm/${LIB}/egl
-namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/hw
-namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/hw
-namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/egl
-namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/egl
-
-namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
-namespace.vndk.asan.permitted.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%/hw
-
-# When these NDK libs are required inside this namespace, then it is redirected
-# to the default namespace. This is possible since their ABI is stable across
-# Android releases.
-namespace.vndk.links = default
-namespace.vndk.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-###############################################################################
-# Namespace config for vendor processes. In O, no restriction is enforced for
-# them. However, in O-MR1, access to /system/${LIB} will not be allowed to
-# the default namespace. 'system' namespace will be added to give limited
-# (LL-NDK only) access.
-###############################################################################
-[vendor]
-additional.namespaces = system,vndk
-
-###############################################################################
-# "default" namespace
-#
-# This is the default linker namespace for a vendor process (a process started
-# from /vendor/bin/*). The main executable and the libs under /vendor/lib[64]
-# are loaded directly into this namespace. However, other libs under the system
-# partition (VNDK and LLNDK libraries) are not loaded here but from the
-# separate namespace 'system'. The delegation to the system namespace is done
-# via the 'namespace.default.link.system.shared_libs' property below.
-###############################################################################
-namespace.default.isolated = true
-namespace.default.visible = true
-
-namespace.default.search.paths  = /odm/${LIB}
-namespace.default.search.paths += /vendor/${LIB}
-
-namespace.default.permitted.paths  = /odm
-namespace.default.permitted.paths += /vendor
-
-namespace.default.asan.search.paths  = /data/asan/odm/${LIB}
-namespace.default.asan.search.paths +=           /odm/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.default.asan.search.paths +=           /vendor/${LIB}
-
-namespace.default.asan.permitted.paths  = /data/asan/odm
-namespace.default.asan.permitted.paths +=           /odm
-namespace.default.asan.permitted.paths += /data/asan/vendor
-namespace.default.asan.permitted.paths +=           /vendor
-
-namespace.default.links = system,vndk
-namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES%
-namespace.default.link.vndk.shared_libs  = %VNDK_SAMEPROCESS_LIBRARIES%
-namespace.default.link.vndk.shared_libs += %VNDK_CORE_LIBRARIES%
-
-###############################################################################
-# "vndk" namespace
-#
-# This namespace is where VNDK and VNDK-SP libraries are loaded for
-# a vendor process.
-###############################################################################
-namespace.vndk.isolated = false
-
-namespace.vndk.search.paths  = /odm/${LIB}/vndk
-namespace.vndk.search.paths += /odm/${LIB}/vndk-sp
-namespace.vndk.search.paths += /vendor/${LIB}/vndk
-namespace.vndk.search.paths += /vendor/${LIB}/vndk-sp
-namespace.vndk.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.search.paths += /system/${LIB}/vndk%VNDK_VER%
-
-namespace.vndk.asan.search.paths  = /data/asan/odm/${LIB}/vndk
-namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk
-namespace.vndk.asan.search.paths += /data/asan/odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk
-namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk
-namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
-namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
-
-# When these NDK libs are required inside this namespace, then it is redirected
-# to the system namespace. This is possible since their ABI is stable across
-# Android releases.
-namespace.vndk.links = system,default
-namespace.vndk.link.system.shared_libs  = %LLNDK_LIBRARIES%
-namespace.vndk.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.vndk.link.default.allow_all_shared_libs = true
-
-###############################################################################
-# "system" namespace
-#
-# This namespace is where system libs (VNDK and LLNDK libs) are loaded for
-# a vendor process.
-###############################################################################
-namespace.system.isolated = false
-
-namespace.system.search.paths = /system/${LIB}
-
-namespace.system.asan.search.paths  = /data/asan/system/${LIB}
-namespace.system.asan.search.paths +=           /system/${LIB}
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
new file mode 100644
index 0000000..5256cb1
--- /dev/null
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -0,0 +1,224 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Bionic loader config file.
+#
+
+# Don't change the order here. The first pattern that matches with the
+# absolute path of an executable is selected.
+dir.system = /system/bin/
+dir.system = /system/xbin/
+
+dir.vendor = /odm/bin/
+dir.vendor = /vendor/bin/
+dir.vendor = /data/nativetest/odm
+dir.vendor = /data/nativetest64/odm
+dir.vendor = /data/benchmarktest/odm
+dir.vendor = /data/benchmarktest64/odm
+dir.vendor = /data/nativetest/vendor
+dir.vendor = /data/nativetest64/vendor
+dir.vendor = /data/benchmarktest/vendor
+dir.vendor = /data/benchmarktest64/vendor
+
+dir.system = /data/nativetest
+dir.system = /data/nativetest64
+dir.system = /data/benchmarktest
+dir.system = /data/benchmarktest64
+
+[system]
+additional.namespaces = sphal,vndk,rs
+
+###############################################################################
+# "default" namespace
+#
+# Framework-side code runs in this namespace. However, libs from other
+# partitions are also allowed temporarily.
+###############################################################################
+namespace.default.isolated = false
+
+namespace.default.search.paths  = /system/${LIB}
+namespace.default.search.paths += /odm/${LIB}
+namespace.default.search.paths += /vendor/${LIB}
+
+namespace.default.asan.search.paths  = /data/asan/system/${LIB}
+namespace.default.asan.search.paths +=           /system/${LIB}
+namespace.default.asan.search.paths += /data/asan/odm/${LIB}
+namespace.default.asan.search.paths +=           /odm/${LIB}
+namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
+namespace.default.asan.search.paths +=           /vendor/${LIB}
+
+###############################################################################
+# "sphal" namespace
+#
+# SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
+# loaded inside system processes. libEGL_<chipset>.so, libGLESv2_<chipset>.so,
+# android.hardware.graphics.mapper@2.0-impl.so, etc are SP-HALs.
+#
+# This namespace is exclusivly for SP-HALs. When the framework tries to dynami-
+# cally load SP-HALs, android_dlopen_ext() is used to explicitly specifying
+# that they should be searched and loaded from this namespace.
+#
+# Note that there is no link from the default namespace to this namespace.
+###############################################################################
+namespace.sphal.isolated = true
+namespace.sphal.visible = true
+
+namespace.sphal.search.paths  = /odm/${LIB}
+namespace.sphal.search.paths += /vendor/${LIB}
+
+namespace.sphal.permitted.paths  = /odm/${LIB}
+namespace.sphal.permitted.paths += /vendor/${LIB}
+
+namespace.sphal.asan.search.paths  = /data/asan/odm/${LIB}
+namespace.sphal.asan.search.paths +=           /odm/${LIB}
+namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}
+namespace.sphal.asan.search.paths +=           /vendor/${LIB}
+
+namespace.sphal.asan.permitted.paths  = /data/asan/odm/${LIB}
+namespace.sphal.asan.permitted.paths +=           /odm/${LIB}
+namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}
+namespace.sphal.asan.permitted.paths +=           /vendor/${LIB}
+
+# Once in this namespace, access to libraries in /system/lib is restricted. Only
+# libs listed here can be used.
+namespace.sphal.links = default,vndk,rs
+
+namespace.sphal.link.default.shared_libs  = %LLNDK_LIBRARIES%
+namespace.sphal.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
+namespace.sphal.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
+
+# Renderscript gets separate namespace
+namespace.sphal.link.rs.shared_libs = libRS_internal.so
+
+###############################################################################
+# "rs" namespace
+#
+# This namespace is exclusively for Renderscript internal libraries.
+# This namespace has slightly looser restriction than the vndk namespace because
+# of the genuine characteristics of Renderscript; /data is in the permitted path
+# to load the compiled *.so file and libmediandk.so can be used here.
+###############################################################################
+namespace.rs.isolated = true
+namespace.rs.visible = true
+
+namespace.rs.search.paths  = /odm/${LIB}/vndk-sp
+namespace.rs.search.paths += /vendor/${LIB}/vndk-sp
+namespace.rs.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
+namespace.rs.search.paths += /odm/${LIB}
+namespace.rs.search.paths += /vendor/${LIB}
+
+namespace.rs.permitted.paths  = /odm/${LIB}
+namespace.rs.permitted.paths += /vendor/${LIB}
+namespace.rs.permitted.paths += /data
+
+namespace.rs.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
+namespace.rs.asan.search.paths +=           /odm/${LIB}/vndk-sp
+namespace.rs.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
+namespace.rs.asan.search.paths +=           /vendor/${LIB}/vndk-sp
+namespace.rs.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
+namespace.rs.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
+namespace.rs.asan.search.paths += /data/asan/odm/${LIB}
+namespace.rs.asan.search.paths +=           /odm/${LIB}
+namespace.rs.asan.search.paths += /data/asan/vendor/${LIB}
+namespace.rs.asan.search.paths +=           /vendor/${LIB}
+
+namespace.rs.asan.permitted.paths  = /data/asan/odm/${LIB}
+namespace.rs.asan.permitted.paths +=           /odm/${LIB}
+namespace.rs.asan.permitted.paths += /data/asan/vendor/${LIB}
+namespace.rs.asan.permitted.paths +=           /vendor/${LIB}
+namespace.rs.asan.permitted.paths += /data
+
+namespace.rs.links = default,vndk
+
+namespace.rs.link.default.shared_libs  =  %LLNDK_LIBRARIES%
+namespace.rs.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+# Private LLNDK libs (e.g. libft2.so) are exceptionally allowed to this
+# namespace because RS framework libs are using them.
+namespace.rs.link.default.shared_libs += %PRIVATE_LLNDK_LIBRARIES%
+
+namespace.rs.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
+
+###############################################################################
+# "vndk" namespace
+#
+# This namespace is exclusively for vndk-sp libs.
+###############################################################################
+namespace.vndk.isolated = true
+namespace.vndk.visible = true
+
+namespace.vndk.search.paths  = /odm/${LIB}/vndk-sp
+namespace.vndk.search.paths += /vendor/${LIB}/vndk-sp
+namespace.vndk.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
+
+namespace.vndk.permitted.paths  = /odm/${LIB}/hw
+namespace.vndk.permitted.paths += /odm/${LIB}/egl
+namespace.vndk.permitted.paths += /vendor/${LIB}/hw
+namespace.vndk.permitted.paths += /vendor/${LIB}/egl
+# This is exceptionally required since android.hidl.memory@1.0-impl.so is here
+namespace.vndk.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER%/hw
+
+namespace.vndk.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
+namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk-sp
+namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
+namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk-sp
+namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
+namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
+
+namespace.vndk.asan.permitted.paths  = /data/asan/odm/${LIB}/hw
+namespace.vndk.asan.permitted.paths +=           /odm/${LIB}/hw
+namespace.vndk.asan.permitted.paths += /data/asan/odm/${LIB}/egl
+namespace.vndk.asan.permitted.paths +=           /odm/${LIB}/egl
+namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/hw
+namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/hw
+namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/egl
+namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/egl
+
+namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
+namespace.vndk.asan.permitted.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%/hw
+
+# When these NDK libs are required inside this namespace, then it is redirected
+# to the default namespace. This is possible since their ABI is stable across
+# Android releases.
+namespace.vndk.links = default
+namespace.vndk.link.default.shared_libs  = %LLNDK_LIBRARIES%
+namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
+###############################################################################
+# Namespace config for vendor processes. In O, no restriction is enforced for
+# them. However, in O-MR1, access to /system/${LIB} will not be allowed to
+# the default namespace. 'system' namespace will be added to give limited
+# (LL-NDK only) access.
+###############################################################################
+[vendor]
+namespace.default.isolated = false
+
+namespace.default.search.paths  = /odm/${LIB}
+namespace.default.search.paths += /odm/${LIB}/vndk
+namespace.default.search.paths += /odm/${LIB}/vndk-sp
+namespace.default.search.paths += /vendor/${LIB}
+namespace.default.search.paths += /vendor/${LIB}/vndk
+namespace.default.search.paths += /vendor/${LIB}/vndk-sp
+
+# Access to system libraries are allowed
+namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
+namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
+namespace.default.search.paths += /system/${LIB}
+
+namespace.default.asan.search.paths  = /data/asan/odm/${LIB}
+namespace.default.asan.search.paths +=           /odm/${LIB}
+namespace.default.asan.search.paths += /data/asan/odm/${LIB}/vndk
+namespace.default.asan.search.paths +=           /odm/${LIB}/vndk
+namespace.default.asan.search.paths += /data/asan/odm/${LIB}/vndk-sp
+namespace.default.asan.search.paths +=           /odm/${LIB}/vndk-sp
+namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
+namespace.default.asan.search.paths +=           /vendor/${LIB}
+namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/vndk
+namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk
+namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
+namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk-sp
+namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
+namespace.default.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
+namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
+namespace.default.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
+namespace.default.asan.search.paths += /data/asan/system/${LIB}
+namespace.default.asan.search.paths +=           /system/${LIB}