Merge "Add vendor_available to liblog_headers."
diff --git a/base/chrono_utils.cpp b/base/chrono_utils.cpp
index 5eedf3b..b6bf701 100644
--- a/base/chrono_utils.cpp
+++ b/base/chrono_utils.cpp
@@ -33,5 +33,10 @@
 #endif  // __ANDROID__
 }
 
+std::ostream& operator<<(std::ostream& os, const Timer& t) {
+  os << t.duration().count() << "ms";
+  return os;
+}
+
 }  // namespace base
 }  // namespace android
diff --git a/base/chrono_utils_test.cpp b/base/chrono_utils_test.cpp
index 057132d..da442f4 100644
--- a/base/chrono_utils_test.cpp
+++ b/base/chrono_utils_test.cpp
@@ -19,6 +19,9 @@
 #include <time.h>
 
 #include <chrono>
+#include <sstream>
+#include <string>
+#include <thread>
 
 #include <gtest/gtest.h>
 
@@ -42,5 +45,36 @@
   EXPECT_EQ(now, boot_seconds);
 }
 
+template <typename T>
+void ExpectAboutEqual(T expected, T actual) {
+  auto expected_upper_bound = expected * 1.05f;
+  auto expected_lower_bound = expected * .95;
+  EXPECT_GT(expected_upper_bound, actual);
+  EXPECT_LT(expected_lower_bound, actual);
+}
+
+TEST(ChronoUtilsTest, TimerDurationIsSane) {
+  auto start = boot_clock::now();
+  Timer t;
+  std::this_thread::sleep_for(50ms);
+  auto stop = boot_clock::now();
+  auto stop_timer = t.duration();
+
+  auto expected = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
+  ExpectAboutEqual(expected, stop_timer);
+}
+
+TEST(ChronoUtilsTest, TimerOstream) {
+  Timer t;
+  std::this_thread::sleep_for(50ms);
+  auto stop_timer = t.duration().count();
+  std::stringstream os;
+  os << t;
+  decltype(stop_timer) stop_timer_from_stream;
+  os >> stop_timer_from_stream;
+  EXPECT_NE(0, stop_timer);
+  ExpectAboutEqual(stop_timer, stop_timer_from_stream);
+}
+
 }  // namespace base
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/base/include/android-base/chrono_utils.h b/base/include/android-base/chrono_utils.h
index 0086425..7679d4c 100644
--- a/base/include/android-base/chrono_utils.h
+++ b/base/include/android-base/chrono_utils.h
@@ -18,6 +18,9 @@
 #define ANDROID_BASE_CHRONO_UTILS_H
 
 #include <chrono>
+#include <sstream>
+
+using namespace std::chrono_literals;
 
 namespace android {
 namespace base {
@@ -31,6 +34,20 @@
   static time_point now();
 };
 
+class Timer {
+ public:
+  Timer() : start_(boot_clock::now()) {}
+
+  std::chrono::milliseconds duration() const {
+    return std::chrono::duration_cast<std::chrono::milliseconds>(boot_clock::now() - start_);
+  }
+
+ private:
+  boot_clock::time_point start_;
+};
+
+std::ostream& operator<<(std::ostream& os, const Timer& t);
+
 }  // namespace base
 }  // namespace android
 
diff --git a/init/action.cpp b/init/action.cpp
index 4a3ab48..4ec5f17 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -16,6 +16,7 @@
 
 #include "action.h"
 
+#include <android-base/chrono_utils.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
@@ -90,19 +91,18 @@
 }
 
 void Action::ExecuteCommand(const Command& command) const {
-    Timer t;
+    android::base::Timer t;
     int result = command.InvokeFunc();
 
-    double duration_ms = t.duration_s() * 1000;
+    auto duration = t.duration();
     // Any action longer than 50ms will be warned to user as slow operation
-    if (duration_ms > 50.0 ||
-        android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
+    if (duration > 50ms || android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
         std::string trigger_name = BuildTriggersString();
         std::string cmd_str = command.BuildCommandString();
 
         LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << " (" << filename_
-                  << ":" << command.line() << ") returned " << result << " took " << duration_ms
-                  << "ms.";
+                  << ":" << command.line() << ") returned " << result << " took "
+                  << duration.count() << "ms.";
     }
 }
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index a9024bd..56d0ae2 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -39,6 +39,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
@@ -555,9 +556,9 @@
     }
 
     std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix;
-    Timer t;
+    android::base::Timer t;
     int ret =  mount_fstab(fstabfile, mount_mode);
-    property_set(prop_name, std::to_string(t.duration_ms()));
+    property_set(prop_name, std::to_string(t.duration().count()));
 
     if (import_rc) {
         /* Paths of .rc files are specified at the 2nd argument and beyond */
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 860b30b..b686885 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -24,12 +24,12 @@
 #include <string>
 #include <thread>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 
-#include "util.h"
-
+using android::base::Timer;
 using android::base::unique_fd;
 using android::base::WriteFully;
 
diff --git a/init/init.cpp b/init/init.cpp
index 1568ee9..377c7d1 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -73,6 +73,7 @@
 
 using android::base::boot_clock;
 using android::base::GetProperty;
+using android::base::Timer;
 
 namespace android {
 namespace init {
@@ -232,7 +233,7 @@
         panic();
     }
 
-    property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration_ms()));
+    property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration().count()));
     return 0;
 }
 
@@ -888,7 +889,7 @@
         }
 
         // init's first stage can't set properties, so pass the time to the second stage.
-        setenv("INIT_SELINUX_TOOK", std::to_string(t.duration_ms()).c_str(), 1);
+        setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);
     } else {
         selinux_init_all_handles();
     }
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index be57f8b..0f7e38f 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -25,6 +25,7 @@
 #include <string>
 #include <vector>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/strings.h>
@@ -36,7 +37,7 @@
 #include "uevent_listener.h"
 #include "util.h"
 
-using namespace std::chrono_literals;
+using android::base::Timer;
 
 namespace android {
 namespace init {
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index e76d589..9f7089b 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -18,6 +18,7 @@
 
 #include <dirent.h>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
@@ -111,7 +112,7 @@
 
 bool Parser::ParseConfigFile(const std::string& path) {
     LOG(INFO) << "Parsing file " << path << "...";
-    Timer t;
+    android::base::Timer t;
     std::string data;
     std::string err;
     if (!ReadFile(path, &data, &err)) {
diff --git a/init/init_parser_test.cpp b/init/init_parser_test.cpp
index 38b8275..95f269a 100644
--- a/init/init_parser_test.cpp
+++ b/init/init_parser_test.cpp
@@ -16,13 +16,14 @@
 
 #include "init_parser.h"
 
-#include "init.h"
-#include "service.h"
+#include <string>
+#include <vector>
 
 #include <gtest/gtest.h>
 
-#include <string>
-#include <vector>
+#include "init.h"
+#include "service.h"
+#include "util.h"
 
 namespace android {
 namespace init {
diff --git a/init/property_service.cpp b/init/property_service.cpp
index b7907e5..fd14bd6 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -42,6 +42,7 @@
 #include <queue>
 #include <vector>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
@@ -55,6 +56,8 @@
 #include "init.h"
 #include "util.h"
 
+using android::base::Timer;
+
 #define PERSISTENT_PROPERTY_DIR  "/data/property"
 #define RECOVERY_MOUNT_POINT "/recovery"
 
@@ -350,7 +353,7 @@
     while (*timeout_ms > 0) {
       Timer timer;
       int nr = poll(ufds, 1, *timeout_ms);
-      uint64_t millis = timer.duration_ms();
+      uint64_t millis = timer.duration().count();
       *timeout_ms = (millis > *timeout_ms) ? 0 : *timeout_ms - millis;
 
       if (nr > 0) {
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 38d603a..969caec 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -35,6 +35,7 @@
 #include <thread>
 #include <vector>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
@@ -54,6 +55,7 @@
 #include "service.h"
 
 using android::base::StringPrintf;
+using android::base::Timer;
 
 namespace android {
 namespace init {
@@ -161,7 +163,8 @@
 }
 
 static void LogShutdownTime(UmountStat stat, Timer* t) {
-    LOG(WARNING) << "powerctl_shutdown_time_ms:" << std::to_string(t->duration_ms()) << ":" << stat;
+    LOG(WARNING) << "powerctl_shutdown_time_ms:" << std::to_string(t->duration().count()) << ":"
+                 << stat;
 }
 
 // Determines whether the system is capable of rebooting. This is conservative,
@@ -254,7 +257,7 @@
     }
 }
 
-static UmountStat UmountPartitions(int timeoutMs) {
+static UmountStat UmountPartitions(std::chrono::milliseconds timeout) {
     Timer t;
     UmountStat stat = UMOUNT_STAT_TIMEOUT;
     int retry = 0;
@@ -272,7 +275,7 @@
             stat = UMOUNT_STAT_SUCCESS;
             break;
         }
-        if ((timeoutMs < t.duration_ms()) && retry > 0) {  // try umount at least once
+        if ((timeout < t.duration()) && retry > 0) {  // try umount at least once
             stat = UMOUNT_STAT_TIMEOUT;
             break;
         }
@@ -301,7 +304,7 @@
  *
  * return true when umount was successful. false when timed out.
  */
-static UmountStat TryUmountAndFsck(bool runFsck, int timeoutMs) {
+static UmountStat TryUmountAndFsck(bool runFsck, std::chrono::milliseconds timeout) {
     Timer t;
     std::vector<MountEntry> block_devices;
     std::vector<MountEntry> emulated_devices;
@@ -312,13 +315,13 @@
         return UMOUNT_STAT_ERROR;
     }
 
-    UmountStat stat = UmountPartitions(timeoutMs - t.duration_ms());
+    UmountStat stat = UmountPartitions(timeout - t.duration());
     if (stat != UMOUNT_STAT_SUCCESS) {
         LOG(INFO) << "umount timeout, last resort, kill all and try";
         if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(false);
         KillAllProcesses();
         // even if it succeeds, still it is timeout and do not run fsck with all processes killed
-        UmountPartitions(0);
+        UmountPartitions(0ms);
         if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(true);
     }
 
@@ -352,15 +355,14 @@
         abort();
     }
 
-    constexpr unsigned int shutdownTimeoutDefault = 6;
-    unsigned int shutdownTimeout = shutdownTimeoutDefault;
-    if (SHUTDOWN_ZERO_TIMEOUT) {  // eng build
-        shutdownTimeout = 0;
-    } else {
-        shutdownTimeout =
-            android::base::GetUintProperty("ro.build.shutdown_timeout", shutdownTimeoutDefault);
+    auto shutdown_timeout = 0s;
+    if (!SHUTDOWN_ZERO_TIMEOUT) {
+        constexpr unsigned int shutdown_timeout_default = 6;
+        auto shutdown_timeout_property =
+            android::base::GetUintProperty("ro.build.shutdown_timeout", shutdown_timeout_default);
+        shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
     }
-    LOG(INFO) << "Shutdown timeout: " << shutdownTimeout;
+    LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " seconds";
 
     // keep debugging tools until non critical ones are all gone.
     const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
@@ -387,7 +389,7 @@
 
     // optional shutdown step
     // 1. terminate all services except shutdown critical ones. wait for delay to finish
-    if (shutdownTimeout > 0) {
+    if (shutdown_timeout > 0s) {
         LOG(INFO) << "terminating init services";
 
         // Ask all services to terminate except shutdown critical ones.
@@ -396,9 +398,9 @@
         });
 
         int service_count = 0;
-        // Up to half as long as shutdownTimeout or 3 seconds, whichever is lower.
-        unsigned int terminationWaitTimeout = std::min<unsigned int>((shutdownTimeout + 1) / 2, 3);
-        while (t.duration_s() < terminationWaitTimeout) {
+        // Up to half as long as shutdown_timeout or 3 seconds, whichever is lower.
+        auto termination_wait_timeout = std::min((shutdown_timeout + 1s) / 2, 3s);
+        while (t.duration() < termination_wait_timeout) {
             ServiceManager::GetInstance().ReapAnyOutstandingChildren();
 
             service_count = 0;
@@ -446,7 +448,7 @@
     });
     // 4. sync, try umount, and optionally run fsck for user shutdown
     sync();
-    UmountStat stat = TryUmountAndFsck(runFsck, shutdownTimeout * 1000 - t.duration_ms());
+    UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
     // Follow what linux shutdown is doing: one more sync with little bit delay
     sync();
     std::this_thread::sleep_for(100ms);
diff --git a/init/service.cpp b/init/service.cpp
index 6b36526..7a657c8 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -633,10 +633,10 @@
     return (this->*parser)(args, err);
 }
 
-bool Service::ExecStart(std::unique_ptr<Timer>* exec_waiter) {
+bool Service::ExecStart(std::unique_ptr<android::base::Timer>* exec_waiter) {
     flags_ |= SVC_EXEC | SVC_ONESHOT;
 
-    exec_waiter->reset(new Timer);
+    exec_waiter->reset(new android::base::Timer);
 
     if (!Start()) {
         exec_waiter->reset();
@@ -1127,7 +1127,8 @@
     if (svc) {
         name = StringPrintf("Service '%s' (pid %d)", svc->name().c_str(), pid);
         if (svc->flags() & SVC_EXEC) {
-            wait_string = StringPrintf(" waiting took %f seconds", exec_waiter_->duration_s());
+            wait_string = StringPrintf(" waiting took %f seconds",
+                                       exec_waiter_->duration().count() / 1000.0f);
         }
     } else {
         name = StringPrintf("Untracked pid %d", pid);
diff --git a/init/service.h b/init/service.h
index 40b4745..f682abd 100644
--- a/init/service.h
+++ b/init/service.h
@@ -32,7 +32,6 @@
 #include "descriptors.h"
 #include "init_parser.h"
 #include "keyword_map.h"
-#include "util.h"
 
 #define SVC_DISABLED 0x001        // do not autostart with class
 #define SVC_ONESHOT 0x002         // do not restart on exit
@@ -76,7 +75,7 @@
 
     bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; }
     bool ParseLine(const std::vector<std::string>& args, std::string* err);
-    bool ExecStart(std::unique_ptr<Timer>* exec_waiter);
+    bool ExecStart(std::unique_ptr<android::base::Timer>* exec_waiter);
     bool Start();
     bool StartIfNotDisabled();
     bool Enable();
@@ -218,7 +217,7 @@
     bool ReapOneProcess();
 
     static int exec_count_; // Every service needs a unique name.
-    std::unique_ptr<Timer> exec_waiter_;
+    std::unique_ptr<android::base::Timer> exec_waiter_;
 
     std::vector<std::unique_ptr<Service>> services_;
 };
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index a713beb..c0eae1e 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -27,6 +27,7 @@
 #include <set>
 #include <thread>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <selinux/android.h>
@@ -198,7 +199,7 @@
 }
 
 void ColdBoot::Run() {
-    Timer cold_boot_timer;
+    android::base::Timer cold_boot_timer;
 
     RegenerateUevents();
 
@@ -209,7 +210,7 @@
     WaitForSubProcesses();
 
     close(open(COLDBOOT_DONE, O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
-    LOG(INFO) << "Coldboot took " << cold_boot_timer;
+    LOG(INFO) << "Coldboot took " << cold_boot_timer.duration().count() / 1000.0f << " seconds";
 }
 
 DeviceHandler CreateDeviceHandler() {
diff --git a/init/util.cpp b/init/util.cpp
index 479179e..2792794 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -374,11 +374,6 @@
     DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
 }
 
-std::ostream& operator<<(std::ostream& os, const Timer& t) {
-    os << t.duration_s() << " seconds";
-    return os;
-}
-
 // Reads the content of device tree file under kAndroidDtDir directory.
 // Returns true if the read is success, false otherwise.
 bool read_android_dt_file(const std::string& sub_path, std::string* dt_content) {
diff --git a/init/util.h b/init/util.h
index 346953f..452df2d 100644
--- a/init/util.h
+++ b/init/util.h
@@ -44,26 +44,6 @@
 bool ReadFile(const std::string& path, std::string* content, std::string* err);
 bool WriteFile(const std::string& path, const std::string& content, std::string* err);
 
-class Timer {
-  public:
-    Timer() : start_(boot_clock::now()) {}
-
-    double duration_s() const {
-        typedef std::chrono::duration<double> double_duration;
-        return std::chrono::duration_cast<double_duration>(boot_clock::now() - start_).count();
-    }
-
-    int64_t duration_ms() const {
-        return std::chrono::duration_cast<std::chrono::milliseconds>(boot_clock::now() - start_)
-            .count();
-    }
-
-  private:
-    android::base::boot_clock::time_point start_;
-};
-
-std::ostream& operator<<(std::ostream& os, const Timer& t);
-
 bool DecodeUid(const std::string& name, uid_t* uid, std::string* err);
 
 int mkdir_recursive(const std::string& pathname, mode_t mode, selabel_handle* sehandle);
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index ab96429..91044ab 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -89,7 +89,7 @@
 LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
 LOCAL_STATIC_LIBRARIES := libgtest libgtest_main
-LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_COMPATIBILITY_SUITE := cts vts
 LOCAL_CTS_TEST_PACKAGE := android.core.liblog
 include $(BUILD_CTS_EXECUTABLE)
 
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index f5d4e1c..9b8248e 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -43,9 +43,6 @@
 
 using namespace std::chrono_literals;
 
-// Uncomment line below use memory cgroups for keeping track of (forked) PIDs
-// #define USE_MEMCG 1
-
 #define MEM_CGROUP_PATH "/dev/memcg/apps"
 #define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks"
 #define ACCT_CGROUP_PATH "/acct"
@@ -91,7 +88,6 @@
 };
 
 static const char* getCgroupRootPath() {
-#ifdef USE_MEMCG
     static const char* cgroup_root_path = NULL;
     std::call_once(init_path_flag, [&]() {
             // Check if mem cgroup is mounted, only then check for write-access to avoid
@@ -100,9 +96,6 @@
                     ACCT_CGROUP_PATH : MEM_CGROUP_PATH;
             });
     return cgroup_root_path;
-#else
-    return ACCT_CGROUP_PATH;
-#endif
 }
 
 static int convertUidToPath(char *path, size_t size, uid_t uid)
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index 6f76e76..87e2684 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -211,7 +211,6 @@
     return;
 
 overflow:
-    LOG_EVENT_INT(78001, cli->getUid());
     cli->sendMsg(500, "Command too long", false);
     goto out;
 }
diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp
index 896dad3..aad0394 100644
--- a/libsysutils/src/NetlinkListener.cpp
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -57,8 +57,6 @@
     count = TEMP_FAILURE_RETRY(uevent_kernel_recv(socket,
             mBuffer, sizeof(mBuffer), require_group, &uid));
     if (count < 0) {
-        if (uid > 0)
-            LOG_EVENT_INT(65537, uid);
         SLOGE("recvmsg failed (%s)", strerror(errno));
         return false;
     }
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 03a9a54..a5af0a0 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -31,6 +31,15 @@
         },
     },
 
+    arch: {
+        mips: {
+            enabled: false,
+        },
+        mips64: {
+            enabled: false,
+        },
+    },
+
     multilib: {
         lib32: {
             suffix: "32",
@@ -64,6 +73,15 @@
         "Symbols.cpp",
     ],
 
+    arch: {
+        x86: {
+            srcs: ["AsmGetRegsX86.S"],
+        },
+        x86_64: {
+            srcs: ["AsmGetRegsX86_64.S"],
+        },
+    },
+
     shared_libs: [
         "libbase",
         "liblog",
@@ -112,6 +130,7 @@
         "tests/MemoryTest.cpp",
         "tests/RegsTest.cpp",
         "tests/SymbolsTest.cpp",
+        "tests/UnwindTest.cpp",
     ],
 
     cflags: [
diff --git a/libunwindstack/AsmGetRegsX86.S b/libunwindstack/AsmGetRegsX86.S
new file mode 100644
index 0000000..14927a3
--- /dev/null
+++ b/libunwindstack/AsmGetRegsX86.S
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+  .text
+  .global AsmGetRegs
+  .balign 16
+  .type AsmGetRegs, @function
+AsmGetRegs:
+  .cfi_startproc
+  mov 4(%esp), %eax
+  movl $0, (%eax)
+  movl %ecx, 4(%eax)
+  movl %edx, 8(%eax)
+  movl %ebx, 12(%eax)
+
+  /* ESP */
+  leal 4(%esp), %ecx
+  movl %ecx, 16(%eax)
+
+  movl %ebp, 20(%eax)
+  movl %esi, 24(%eax)
+  movl %edi, 28(%eax)
+
+  /* EIP */
+  movl (%esp), %ecx
+  movl %ecx, 32(%eax)
+
+  movl %cs, 36(%eax)
+  movl %ss, 40(%eax)
+  movl %ds, 44(%eax)
+  movl %es, 48(%eax)
+  movl %fs, 52(%eax)
+  movl %gs, 56(%eax)
+  ret
+
+  .cfi_endproc
+  .size AsmGetRegs, .-AsmGetRegs
diff --git a/libunwindstack/AsmGetRegsX86_64.S b/libunwindstack/AsmGetRegsX86_64.S
new file mode 100644
index 0000000..4cd3b6f
--- /dev/null
+++ b/libunwindstack/AsmGetRegsX86_64.S
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+  .text
+  .global AsmGetRegs
+  .balign 16
+  .type AsmGetRegs, @function
+AsmGetRegs:
+  .cfi_startproc
+  movq %rax, (%rdi)
+  movq %rdx, 8(%rdi)
+  movq %rcx, 16(%rdi)
+  movq %rbx, 24(%rdi)
+  movq %rsi, 32(%rdi)
+  movq %rdi, 40(%rdi)
+  movq %rbp, 48(%rdi)
+
+  /* RSP */
+  lea 8(%rsp), %rax
+  movq %rax, 56(%rdi)
+
+  movq %r8, 64(%rdi)
+  movq %r9, 72(%rdi)
+  movq %r10, 80(%rdi)
+  movq %r11, 88(%rdi)
+  movq %r12, 96(%rdi)
+  movq %r13, 104(%rdi)
+  movq %r14, 112(%rdi)
+  movq %r15, 120(%rdi)
+
+  /* RIP */
+  movq (%rsp), %rax
+  movq %rax, 128(%rdi)
+  ret
+
+  .cfi_endproc
+  .size AsmGetRegs, .-AsmGetRegs
diff --git a/libunwindstack/Machine.h b/libunwindstack/Machine.h
index 323ce80..bcc3788 100644
--- a/libunwindstack/Machine.h
+++ b/libunwindstack/Machine.h
@@ -83,47 +83,51 @@
   ARM64_REG_LR = ARM64_REG_R30,
 };
 
+// Matches the numbers for the registers as generated by compilers.
+// If this is changed, then unwinding will fail.
 enum X86Reg : uint16_t {
   X86_REG_EAX = 0,
-  X86_REG_ECX,
-  X86_REG_EDX,
-  X86_REG_EBX,
-  X86_REG_ESP,
-  X86_REG_EBP,
-  X86_REG_ESI,
-  X86_REG_EDI,
-  X86_REG_EIP,
-  X86_REG_EFL,
-  X86_REG_CS,
-  X86_REG_SS,
-  X86_REG_DS,
-  X86_REG_ES,
-  X86_REG_FS,
-  X86_REG_GS,
+  X86_REG_ECX = 1,
+  X86_REG_EDX = 2,
+  X86_REG_EBX = 3,
+  X86_REG_ESP = 4,
+  X86_REG_EBP = 5,
+  X86_REG_ESI = 6,
+  X86_REG_EDI = 7,
+  X86_REG_EIP = 8,
+  X86_REG_EFL = 9,
+  X86_REG_CS = 10,
+  X86_REG_SS = 11,
+  X86_REG_DS = 12,
+  X86_REG_ES = 13,
+  X86_REG_FS = 14,
+  X86_REG_GS = 15,
   X86_REG_LAST,
 
   X86_REG_SP = X86_REG_ESP,
   X86_REG_PC = X86_REG_EIP,
 };
 
+// Matches the numbers for the registers as generated by compilers.
+// If this is changed, then unwinding will fail.
 enum X86_64Reg : uint16_t {
   X86_64_REG_RAX = 0,
-  X86_64_REG_RDX,
-  X86_64_REG_RCX,
-  X86_64_REG_RBX,
-  X86_64_REG_RSI,
-  X86_64_REG_RDI,
-  X86_64_REG_RBP,
-  X86_64_REG_RSP,
-  X86_64_REG_R8,
-  X86_64_REG_R9,
-  X86_64_REG_R10,
-  X86_64_REG_R11,
-  X86_64_REG_R12,
-  X86_64_REG_R13,
-  X86_64_REG_R14,
-  X86_64_REG_R15,
-  X86_64_REG_RIP,
+  X86_64_REG_RDX = 1,
+  X86_64_REG_RCX = 2,
+  X86_64_REG_RBX = 3,
+  X86_64_REG_RSI = 4,
+  X86_64_REG_RDI = 5,
+  X86_64_REG_RBP = 6,
+  X86_64_REG_RSP = 7,
+  X86_64_REG_R8 = 8,
+  X86_64_REG_R9 = 9,
+  X86_64_REG_R10 = 10,
+  X86_64_REG_R11 = 11,
+  X86_64_REG_R12 = 12,
+  X86_64_REG_R13 = 13,
+  X86_64_REG_R14 = 14,
+  X86_64_REG_R15 = 15,
+  X86_64_REG_RIP = 16,
   X86_64_REG_LAST,
 
   X86_64_REG_SP = X86_64_REG_RSP,
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
index da22b07..92b6e22 100644
--- a/libunwindstack/Regs.cpp
+++ b/libunwindstack/Regs.cpp
@@ -27,6 +27,7 @@
 #include "Machine.h"
 #include "MapInfo.h"
 #include "Regs.h"
+#include "Ucontext.h"
 #include "User.h"
 
 template <typename AddressType>
@@ -88,6 +89,11 @@
   return rel_pc - 4;
 }
 
+void RegsArm::SetFromRaw() {
+  set_pc(regs_[ARM_REG_PC]);
+  set_sp(regs_[ARM_REG_SP]);
+}
+
 RegsArm64::RegsArm64()
     : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
 
@@ -102,6 +108,11 @@
   return rel_pc - 4;
 }
 
+void RegsArm64::SetFromRaw() {
+  set_pc(regs_[ARM64_REG_PC]);
+  set_sp(regs_[ARM64_REG_SP]);
+}
+
 RegsX86::RegsX86()
     : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}
 
@@ -116,6 +127,11 @@
   return rel_pc - 1;
 }
 
+void RegsX86::SetFromRaw() {
+  set_pc(regs_[X86_REG_PC]);
+  set_sp(regs_[X86_REG_SP]);
+}
+
 RegsX86_64::RegsX86_64()
     : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
 
@@ -131,15 +147,17 @@
   return rel_pc - 1;
 }
 
+void RegsX86_64::SetFromRaw() {
+  set_pc(regs_[X86_64_REG_PC]);
+  set_sp(regs_[X86_64_REG_SP]);
+}
+
 static Regs* ReadArm(void* remote_data) {
   arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);
 
   RegsArm* regs = new RegsArm();
   memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
-
-  regs->set_pc(user->regs[ARM_REG_PC]);
-  regs->set_sp(user->regs[ARM_REG_SP]);
-
+  regs->SetFromRaw();
   return regs;
 }
 
@@ -148,9 +166,10 @@
 
   RegsArm64* regs = new RegsArm64();
   memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R31 + 1) * sizeof(uint64_t));
-  regs->set_pc(user->pc);
-  regs->set_sp(user->sp);
-
+  uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
+  reg_data[ARM64_REG_PC] = user->pc;
+  reg_data[ARM64_REG_SP] = user->sp;
+  regs->SetFromRaw();
   return regs;
 }
 
@@ -168,9 +187,7 @@
   (*regs)[X86_REG_ESP] = user->esp;
   (*regs)[X86_REG_EIP] = user->eip;
 
-  regs->set_pc(user->eip);
-  regs->set_sp(user->esp);
-
+  regs->SetFromRaw();
   return regs;
 }
 
@@ -196,9 +213,7 @@
   (*regs)[X86_64_REG_RSP] = user->rsp;
   (*regs)[X86_64_REG_RIP] = user->rip;
 
-  regs->set_pc(user->rip);
-  regs->set_sp(user->rsp);
-
+  regs->SetFromRaw();
   return regs;
 }
 
@@ -231,3 +246,111 @@
   }
   return nullptr;
 }
+
+static Regs* CreateFromArmUcontext(void* ucontext) {
+  arm_ucontext_t* arm_ucontext = reinterpret_cast<arm_ucontext_t*>(ucontext);
+
+  RegsArm* regs = new RegsArm();
+  memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
+  regs->SetFromRaw();
+  return regs;
+}
+
+static Regs* CreateFromArm64Ucontext(void* ucontext) {
+  arm64_ucontext_t* arm64_ucontext = reinterpret_cast<arm64_ucontext_t*>(ucontext);
+
+  RegsArm64* regs = new RegsArm64();
+  memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
+  regs->SetFromRaw();
+  return regs;
+}
+
+static Regs* CreateFromX86Ucontext(void* ucontext) {
+  x86_ucontext_t* x86_ucontext = reinterpret_cast<x86_ucontext_t*>(ucontext);
+
+  RegsX86* regs = new RegsX86();
+  // Put the registers in the expected order.
+  (*regs)[X86_REG_GS] = x86_ucontext->uc_mcontext.gs;
+  (*regs)[X86_REG_FS] = x86_ucontext->uc_mcontext.fs;
+  (*regs)[X86_REG_ES] = x86_ucontext->uc_mcontext.es;
+  (*regs)[X86_REG_DS] = x86_ucontext->uc_mcontext.ds;
+  (*regs)[X86_REG_EDI] = x86_ucontext->uc_mcontext.edi;
+  (*regs)[X86_REG_ESI] = x86_ucontext->uc_mcontext.esi;
+  (*regs)[X86_REG_EBP] = x86_ucontext->uc_mcontext.ebp;
+  (*regs)[X86_REG_ESP] = x86_ucontext->uc_mcontext.esp;
+  (*regs)[X86_REG_EBX] = x86_ucontext->uc_mcontext.ebx;
+  (*regs)[X86_REG_EDX] = x86_ucontext->uc_mcontext.edx;
+  (*regs)[X86_REG_ECX] = x86_ucontext->uc_mcontext.ecx;
+  (*regs)[X86_REG_EAX] = x86_ucontext->uc_mcontext.eax;
+  (*regs)[X86_REG_EIP] = x86_ucontext->uc_mcontext.eip;
+  regs->SetFromRaw();
+  return regs;
+}
+
+static Regs* CreateFromX86_64Ucontext(void* ucontext) {
+  x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast<x86_64_ucontext_t*>(ucontext);
+
+  RegsX86_64* regs = new RegsX86_64();
+  // Put the registers in the expected order.
+
+  // R8-R15
+  memcpy(&(*regs)[X86_64_REG_R8], &x86_64_ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t));
+
+  // Rest of the registers.
+  (*regs)[X86_64_REG_RDI] = x86_64_ucontext->uc_mcontext.rdi;
+  (*regs)[X86_64_REG_RSI] = x86_64_ucontext->uc_mcontext.rsi;
+  (*regs)[X86_64_REG_RBP] = x86_64_ucontext->uc_mcontext.rbp;
+  (*regs)[X86_64_REG_RBX] = x86_64_ucontext->uc_mcontext.rbx;
+  (*regs)[X86_64_REG_RDX] = x86_64_ucontext->uc_mcontext.rdx;
+  (*regs)[X86_64_REG_RAX] = x86_64_ucontext->uc_mcontext.rax;
+  (*regs)[X86_64_REG_RCX] = x86_64_ucontext->uc_mcontext.rcx;
+  (*regs)[X86_64_REG_RSP] = x86_64_ucontext->uc_mcontext.rsp;
+  (*regs)[X86_64_REG_RIP] = x86_64_ucontext->uc_mcontext.rip;
+
+  regs->SetFromRaw();
+  return regs;
+}
+
+Regs* Regs::CreateFromUcontext(uint32_t machine_type, void* ucontext) {
+  switch (machine_type) {
+    case EM_386:
+      return CreateFromX86Ucontext(ucontext);
+    case EM_X86_64:
+      return CreateFromX86_64Ucontext(ucontext);
+    case EM_ARM:
+      return CreateFromArmUcontext(ucontext);
+    case EM_AARCH64:
+      return CreateFromArm64Ucontext(ucontext);
+  }
+  return nullptr;
+}
+
+uint32_t Regs::GetMachineType() {
+#if defined(__arm__)
+  return EM_ARM;
+#elif defined(__aarch64__)
+  return EM_AARCH64;
+#elif defined(__i386__)
+  return EM_386;
+#elif defined(__x86_64__)
+  return EM_X86_64;
+#else
+  abort();
+#endif
+}
+
+Regs* Regs::CreateFromLocal() {
+  Regs* regs;
+#if defined(__arm__)
+  regs = new RegsArm();
+#elif defined(__aarch64__)
+  regs = new RegsArm64();
+#elif defined(__i386__)
+  regs = new RegsX86();
+#elif defined(__x86_64__)
+  regs = new RegsX86_64();
+#else
+  abort();
+#endif
+  return regs;
+}
diff --git a/libunwindstack/Regs.h b/libunwindstack/Regs.h
index 8f5a721..a7567d8 100644
--- a/libunwindstack/Regs.h
+++ b/libunwindstack/Regs.h
@@ -54,10 +54,15 @@
 
   virtual uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) = 0;
 
+  virtual void SetFromRaw() = 0;
+
   uint16_t sp_reg() { return sp_reg_; }
   uint16_t total_regs() { return total_regs_; }
 
+  static uint32_t GetMachineType();
   static Regs* RemoteGet(pid_t pid, uint32_t* machine_type);
+  static Regs* CreateFromUcontext(uint32_t machine_type, void* ucontext);
+  static Regs* CreateFromLocal();
 
  protected:
   uint16_t total_regs_;
@@ -98,6 +103,8 @@
   virtual ~RegsArm() = default;
 
   uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+
+  void SetFromRaw() override;
 };
 
 class RegsArm64 : public RegsImpl<uint64_t> {
@@ -106,6 +113,8 @@
   virtual ~RegsArm64() = default;
 
   uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+
+  void SetFromRaw() override;
 };
 
 class RegsX86 : public RegsImpl<uint32_t> {
@@ -114,6 +123,8 @@
   virtual ~RegsX86() = default;
 
   uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+
+  void SetFromRaw() override;
 };
 
 class RegsX86_64 : public RegsImpl<uint64_t> {
@@ -122,6 +133,8 @@
   virtual ~RegsX86_64() = default;
 
   uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+
+  void SetFromRaw() override;
 };
 
 #endif  // _LIBUNWINDSTACK_REGS_H
diff --git a/libunwindstack/RegsGetLocal.h b/libunwindstack/RegsGetLocal.h
new file mode 100644
index 0000000..8e6d04c
--- /dev/null
+++ b/libunwindstack/RegsGetLocal.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LIBUNWINDSTACK_REGS_GET_LOCAL_H
+#define _LIBUNWINDSTACK_REGS_GET_LOCAL_H
+
+#if defined(__arm__)
+
+inline void RegsGetLocal(Regs* regs) {
+  void* reg_data = regs->RawData();
+  asm volatile(
+      ".align 2\n"
+      "bx pc\n"
+      "nop\n"
+      ".code 32\n"
+      "stmia %[base], {r0-r12}\n"
+      "add %[base], #52\n"
+      "mov r1, r13\n"
+      "mov r2, r14\n"
+      "mov r3, r15\n"
+      "stmia %[base], {r1-r3}\n"
+      "orr %[base], pc, #1\n"
+      "bx %[base]\n"
+      : [base] "+r"(reg_data)
+      :
+      : "memory");
+
+  regs->SetFromRaw();
+}
+
+#elif defined(__aarch64__)
+
+inline void RegsGetLocal(Regs* regs) {
+  void* reg_data = regs->RawData();
+  asm volatile(
+      "1:\n"
+      "stp x0, x1, [%[base], #0]\n"
+      "stp x2, x3, [%[base], #16]\n"
+      "stp x4, x5, [%[base], #32]\n"
+      "stp x6, x7, [%[base], #48]\n"
+      "stp x8, x9, [%[base], #64]\n"
+      "stp x10, x11, [%[base], #80]\n"
+      "stp x12, x13, [%[base], #96]\n"
+      "stp x14, x15, [%[base], #112]\n"
+      "stp x16, x17, [%[base], #128]\n"
+      "stp x18, x19, [%[base], #144]\n"
+      "stp x20, x21, [%[base], #160]\n"
+      "stp x22, x23, [%[base], #176]\n"
+      "stp x24, x25, [%[base], #192]\n"
+      "stp x26, x27, [%[base], #208]\n"
+      "stp x28, x29, [%[base], #224]\n"
+      "str x30, [%[base], #240]\n"
+      "mov x12, sp\n"
+      "adr x13, 1b\n"
+      "stp x12, x13, [%[base], #248]\n"
+      : [base] "+r"(reg_data)
+      :
+      : "x12", "x13", "memory");
+
+  regs->SetFromRaw();
+}
+
+#elif defined(__i386__) || defined(__x86_64__)
+
+extern "C" void AsmGetRegs(void* regs);
+
+inline void RegsGetLocal(Regs* regs) {
+  AsmGetRegs(regs->RawData());
+
+  regs->SetFromRaw();
+}
+
+#endif
+
+#endif  // _LIBUNWINDSTACK_REGS_GET_LOCAL_H
diff --git a/libunwindstack/Ucontext.h b/libunwindstack/Ucontext.h
new file mode 100644
index 0000000..95ba682
--- /dev/null
+++ b/libunwindstack/Ucontext.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LIBUNWINDSTACK_UCONTEXT_H
+#define _LIBUNWINDSTACK_UCONTEXT_H
+
+#include <stdint.h>
+
+//-------------------------------------------------------------------
+// ARM ucontext structures
+//-------------------------------------------------------------------
+struct arm_stack_t {
+  uint32_t ss_sp;    // void __user*
+  int32_t ss_flags;  // int
+  uint32_t ss_size;  // size_t
+};
+
+struct arm_mcontext_t {
+  uint32_t trap_no;             // unsigned long
+  uint32_t error_code;          // unsigned long
+  uint32_t oldmask;             // unsigned long
+  uint32_t regs[ARM_REG_LAST];  // unsigned long
+  uint32_t cpsr;                // unsigned long
+  uint32_t fault_address;       // unsigned long
+};
+
+struct arm_ucontext_t {
+  uint32_t uc_flags;  // unsigned long
+  uint32_t uc_link;   // struct ucontext*
+  arm_stack_t uc_stack;
+  arm_mcontext_t uc_mcontext;
+  // Nothing else is used, so don't define it.
+};
+//-------------------------------------------------------------------
+
+//-------------------------------------------------------------------
+// ARM64 ucontext structures
+//-------------------------------------------------------------------
+struct arm64_stack_t {
+  uint64_t ss_sp;    // void __user*
+  int32_t ss_flags;  // int
+  uint64_t ss_size;  // size_t
+};
+
+struct arm64_sigset_t {
+  uint64_t sig;  // unsigned long
+};
+
+struct arm64_mcontext_t {
+  uint64_t fault_address;         // __u64
+  uint64_t regs[ARM64_REG_LAST];  // __u64
+  uint64_t pstate;                // __u64
+  // Nothing else is used, so don't define it.
+};
+
+struct arm64_ucontext_t {
+  uint64_t uc_flags;  // unsigned long
+  uint64_t uc_link;   // struct ucontext*
+  arm64_stack_t uc_stack;
+  arm64_sigset_t uc_sigmask;
+  // The kernel adds extra padding after uc_sigmask to match glibc sigset_t on ARM64.
+  char __padding[128 - sizeof(arm64_sigset_t)];
+  // The full structure requires 16 byte alignment, but our partial structure
+  // doesn't, so force the alignment.
+  arm64_mcontext_t uc_mcontext __attribute__((aligned(16)));
+};
+//-------------------------------------------------------------------
+
+//-------------------------------------------------------------------
+// X86 ucontext structures
+//-------------------------------------------------------------------
+struct x86_stack_t {
+  uint32_t ss_sp;    // void __user*
+  int32_t ss_flags;  // int
+  uint32_t ss_size;  // size_t
+};
+
+struct x86_mcontext_t {
+  uint32_t gs;
+  uint32_t fs;
+  uint32_t es;
+  uint32_t ds;
+  uint32_t edi;
+  uint32_t esi;
+  uint32_t ebp;
+  uint32_t esp;
+  uint32_t ebx;
+  uint32_t edx;
+  uint32_t ecx;
+  uint32_t eax;
+  uint32_t trapno;
+  uint32_t err;
+  uint32_t eip;
+  uint32_t cs;
+  uint32_t efl;
+  uint32_t uesp;
+  uint32_t ss;
+  // Only care about the registers, skip everything else.
+};
+
+struct x86_ucontext_t {
+  uint32_t uc_flags;  // unsigned long
+  uint32_t uc_link;   // struct ucontext*
+  x86_stack_t uc_stack;
+  x86_mcontext_t uc_mcontext;
+  // Nothing else is used, so don't define it.
+};
+//-------------------------------------------------------------------
+
+//-------------------------------------------------------------------
+// X86_64 ucontext structures
+//-------------------------------------------------------------------
+struct x86_64_stack_t {
+  uint64_t ss_sp;    // void __user*
+  int32_t ss_flags;  // int
+  uint64_t ss_size;  // size_t
+};
+
+struct x86_64_mcontext_t {
+  uint64_t r8;
+  uint64_t r9;
+  uint64_t r10;
+  uint64_t r11;
+  uint64_t r12;
+  uint64_t r13;
+  uint64_t r14;
+  uint64_t r15;
+  uint64_t rdi;
+  uint64_t rsi;
+  uint64_t rbp;
+  uint64_t rbx;
+  uint64_t rdx;
+  uint64_t rax;
+  uint64_t rcx;
+  uint64_t rsp;
+  uint64_t rip;
+  uint64_t efl;
+  uint64_t csgsfs;
+  uint64_t err;
+  uint64_t trapno;
+  uint64_t oldmask;
+  uint64_t cr2;
+  // Only care about the registers, skip everything else.
+};
+
+typedef struct x86_64_ucontext {
+  uint64_t uc_flags;  // unsigned long
+  uint64_t uc_link;   // struct ucontext*
+  x86_64_stack_t uc_stack;
+  x86_64_mcontext_t uc_mcontext;
+  // Nothing else is used, so don't define it.
+} x86_64_ucontext_t;
+//-------------------------------------------------------------------
+
+#endif  // _LIBUNWINDSTACK_UCONTEXT_H
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index d7433e1..b82c841 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -201,4 +201,5 @@
   ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
 
   kill(pid, SIGKILL);
+  ASSERT_EQ(pid, wait(nullptr));
 }
diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp
index e48edf7..7210786 100644
--- a/libunwindstack/tests/MemoryRemoteTest.cpp
+++ b/libunwindstack/tests/MemoryRemoteTest.cpp
@@ -91,6 +91,7 @@
   ASSERT_TRUE(Detach(pid));
 
   kill(pid, SIGKILL);
+  ASSERT_EQ(pid, wait(nullptr));
 }
 
 TEST_F(MemoryRemoteTest, read_fail) {
@@ -131,6 +132,7 @@
   ASSERT_TRUE(Detach(pid));
 
   kill(pid, SIGKILL);
+  ASSERT_EQ(pid, wait(nullptr));
 }
 
 TEST_F(MemoryRemoteTest, read_overflow) {
@@ -160,4 +162,5 @@
   ASSERT_TRUE(Detach(pid));
 
   kill(pid, SIGKILL);
+  ASSERT_EQ(pid, wait(nullptr));
 }
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index ff030c8..c57954c 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -30,6 +30,7 @@
 
   uint64_t GetRelPc(Elf*, const MapInfo*) override { return 0; }
   uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
+  void SetFromRaw() override {}
   bool GetReturnAddressFromDefault(Memory*, uint64_t*) { return false; }
 };
 
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 3056373..dde42de 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -56,7 +56,8 @@
       : RegsImpl<TypeParam>(total_regs, regs_sp, return_loc) {}
   virtual ~RegsTestImpl() = default;
 
-  uint64_t GetAdjustedPc(uint64_t, Elf*) { return 0; }
+  uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
+  void SetFromRaw() override {}
 };
 
 class RegsTest : public ::testing::Test {
@@ -264,3 +265,43 @@
   ASSERT_EQ(0x800U, regs_x86_64.GetRelPc(&invalid_elf, &map_info));
   ASSERT_EQ(0x800U, regs_x86_64.GetAdjustedPc(0x800U, &invalid_elf));
 }
+
+TEST_F(RegsTest, arm_set_from_raw) {
+  RegsArm arm;
+  uint32_t* regs = reinterpret_cast<uint32_t*>(arm.RawData());
+  regs[13] = 0x100;
+  regs[15] = 0x200;
+  arm.SetFromRaw();
+  EXPECT_EQ(0x100U, arm.sp());
+  EXPECT_EQ(0x200U, arm.pc());
+}
+
+TEST_F(RegsTest, arm64_set_from_raw) {
+  RegsArm64 arm64;
+  uint64_t* regs = reinterpret_cast<uint64_t*>(arm64.RawData());
+  regs[31] = 0xb100000000ULL;
+  regs[32] = 0xc200000000ULL;
+  arm64.SetFromRaw();
+  EXPECT_EQ(0xb100000000U, arm64.sp());
+  EXPECT_EQ(0xc200000000U, arm64.pc());
+}
+
+TEST_F(RegsTest, x86_set_from_raw) {
+  RegsX86 x86;
+  uint32_t* regs = reinterpret_cast<uint32_t*>(x86.RawData());
+  regs[4] = 0x23450000;
+  regs[8] = 0xabcd0000;
+  x86.SetFromRaw();
+  EXPECT_EQ(0x23450000U, x86.sp());
+  EXPECT_EQ(0xabcd0000U, x86.pc());
+}
+
+TEST_F(RegsTest, x86_64_set_from_raw) {
+  RegsX86_64 x86_64;
+  uint64_t* regs = reinterpret_cast<uint64_t*>(x86_64.RawData());
+  regs[7] = 0x1200000000ULL;
+  regs[16] = 0x4900000000ULL;
+  x86_64.SetFromRaw();
+  EXPECT_EQ(0x1200000000U, x86_64.sp());
+  EXPECT_EQ(0x4900000000U, x86_64.pc());
+}
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
new file mode 100644
index 0000000..7497b65
--- /dev/null
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <signal.h>
+#include <stdint.h>
+#include <sys/ptrace.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include <gtest/gtest.h>
+
+#include <atomic>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <thread>
+
+#include "Elf.h"
+#include "MapInfo.h"
+#include "Maps.h"
+#include "Memory.h"
+#include "Regs.h"
+#include "RegsGetLocal.h"
+
+static std::atomic_bool g_ready(false);
+static volatile bool g_ready_for_remote = false;
+static std::atomic_bool g_finish(false);
+static std::atomic_uintptr_t g_ucontext;
+
+static void Signal(int, siginfo_t*, void* sigcontext) {
+  g_ucontext = reinterpret_cast<uintptr_t>(sigcontext);
+  while (!g_finish.load()) {
+  }
+}
+
+static std::string ErrorMsg(const char** function_names, size_t index,
+                            std::stringstream& unwind_stream) {
+  return std::string(
+             "Unwind completed without finding all frames\n"
+             "  Looking for function: ") +
+         function_names[index] + "\n" + "Unwind data:\n" + unwind_stream.str();
+}
+
+static void VerifyUnwind(pid_t pid, Memory* memory, Maps* maps, Regs* regs) {
+  const char* function_names[] = {
+      "InnerFunction", "MiddleFunction", "OuterFunction",
+  };
+  size_t function_name_index = 0;
+
+  std::stringstream unwind_stream;
+  unwind_stream << std::hex;
+  for (size_t frame_num = 0; frame_num < 64; frame_num++) {
+    ASSERT_NE(0U, regs->pc()) << ErrorMsg(function_names, function_name_index, unwind_stream);
+    MapInfo* map_info = maps->Find(regs->pc());
+    ASSERT_TRUE(map_info != nullptr) << ErrorMsg(function_names, function_name_index, unwind_stream);
+
+    Elf* elf = map_info->GetElf(pid, true);
+    uint64_t rel_pc = regs->GetRelPc(elf, map_info);
+    uint64_t adjusted_rel_pc = rel_pc;
+    if (frame_num != 0) {
+      adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf);
+    }
+    unwind_stream << "  PC: 0x" << regs->pc() << " Rel: 0x" << adjusted_rel_pc;
+    unwind_stream << " Map: ";
+    if (!map_info->name.empty()) {
+      unwind_stream << map_info->name;
+    } else {
+      unwind_stream << " anonymous";
+    }
+    unwind_stream << "<" << map_info->start << "-" << map_info->end << ">";
+
+    std::string name;
+    uint64_t func_offset;
+    if (elf->GetFunctionName(adjusted_rel_pc, &name, &func_offset)) {
+      if (name == function_names[function_name_index]) {
+        function_name_index++;
+        if (function_name_index == sizeof(function_names) / sizeof(const char*)) {
+          return;
+        }
+      }
+      unwind_stream << " " << name;
+    }
+    unwind_stream << "\n";
+    ASSERT_TRUE(elf->Step(rel_pc + map_info->elf_offset, regs, memory))
+        << ErrorMsg(function_names, function_name_index, unwind_stream);
+  }
+  ASSERT_TRUE(false) << ErrorMsg(function_names, function_name_index, unwind_stream);
+}
+
+// This test assumes that this code is compiled with optimizations turned
+// off. If this doesn't happen, then all of the calls will be optimized
+// away.
+extern "C" void InnerFunction(bool local) {
+  if (local) {
+    LocalMaps maps;
+    ASSERT_TRUE(maps.Parse());
+    std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
+    RegsGetLocal(regs.get());
+    MemoryLocal memory;
+
+    VerifyUnwind(getpid(), &memory, &maps, regs.get());
+  } else {
+    g_ready_for_remote = true;
+    g_ready = true;
+    while (!g_finish.load()) {
+    }
+  }
+}
+
+extern "C" void MiddleFunction(bool local) {
+  InnerFunction(local);
+}
+
+extern "C" void OuterFunction(bool local) {
+  MiddleFunction(local);
+}
+
+TEST(UnwindTest, local) {
+  OuterFunction(true);
+}
+
+TEST(UnwindTest, remote) {
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    OuterFunction(false);
+    exit(0);
+  }
+  ASSERT_NE(-1, pid);
+
+  bool ready = false;
+  uint64_t addr = reinterpret_cast<uint64_t>(&g_ready_for_remote);
+  for (size_t i = 0; i < 100; i++) {
+    ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid, 0, 0));
+    for (size_t j = 0; j < 100; j++) {
+      siginfo_t si;
+      if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
+        // Check to see if process is ready to be unwound.
+        MemoryRemote memory(pid);
+        // Read the remote value to see if we are ready.
+        bool value;
+        if (memory.Read(addr, &value, sizeof(value)) && value) {
+          ready = true;
+          break;
+        }
+      }
+      usleep(1000);
+    }
+    if (ready) {
+      break;
+    }
+    ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0));
+    usleep(1000);
+  }
+  ASSERT_TRUE(read) << "Timed out waiting for remote process to be ready.";
+
+  RemoteMaps maps(pid);
+  ASSERT_TRUE(maps.Parse());
+  MemoryRemote memory(pid);
+  uint32_t machine_type;
+  std::unique_ptr<Regs> regs(Regs::RemoteGet(pid, &machine_type));
+  ASSERT_TRUE(regs.get() != nullptr);
+
+  VerifyUnwind(pid, &memory, &maps, regs.get());
+
+  ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0));
+
+  kill(pid, SIGKILL);
+  ASSERT_EQ(pid, wait(nullptr));
+}
+
+TEST(UnwindTest, from_context) {
+  std::atomic_int tid(0);
+  std::thread thread([&]() {
+    tid = syscall(__NR_gettid);
+    OuterFunction(false);
+  });
+
+  struct sigaction act, oldact;
+  memset(&act, 0, sizeof(act));
+  act.sa_sigaction = Signal;
+  act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+  ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact));
+  // Wait for the tid to get set.
+  for (size_t i = 0; i < 100; i++) {
+    if (tid.load() != 0) {
+      break;
+    }
+    usleep(1000);
+  }
+  ASSERT_NE(0, tid.load());
+  // Portable tgkill method.
+  ASSERT_EQ(0, syscall(__NR_tgkill, getpid(), tid.load(), SIGUSR1)) << "Failed because "
+                                                                    << strerror(errno);
+
+  // Wait for context data.
+  void* ucontext;
+  for (size_t i = 0; i < 200; i++) {
+    ucontext = reinterpret_cast<void*>(g_ucontext.load());
+    if (ucontext != nullptr) {
+      break;
+    }
+    usleep(1000);
+  }
+  ASSERT_TRUE(ucontext != nullptr) << "Timed out waiting for thread to respond to signal.";
+
+  LocalMaps maps;
+  ASSERT_TRUE(maps.Parse());
+  std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::GetMachineType(), ucontext));
+  MemoryLocal memory;
+
+  VerifyUnwind(tid.load(), &memory, &maps, regs.get());
+
+  ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr));
+
+  g_finish = true;
+  thread.join();
+}
diff --git a/logd/tests/Android.mk b/logd/tests/Android.mk
index 1915677..a0875ea 100644
--- a/logd/tests/Android.mk
+++ b/logd/tests/Android.mk
@@ -63,7 +63,7 @@
 LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 LOCAL_SHARED_LIBRARIES := libbase libcutils liblog libselinux
 LOCAL_STATIC_LIBRARIES := libgtest libgtest_main
-LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_COMPATIBILITY_SUITE := cts vts
 LOCAL_CTS_TEST_PACKAGE := android.core.logd
 include $(BUILD_CTS_EXECUTABLE)
 
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 2e5575f..046557e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -194,7 +194,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := ld.config.txt
-ifeq ($(PRODUCT_FULL_TREBLE),true)
+ifeq ($(PRODUCT_FULL_TREBLE)|$(SANITIZE_TARGET),true|)
 LOCAL_SRC_FILES := etc/ld.config.txt
 else
 LOCAL_SRC_FILES := etc/ld.config.legacy.txt
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 450beab..14ea0f0 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -36,6 +36,8 @@
     mount cgroup none /dev/memcg memory
     # app mem cgroups, used by activity manager, lmkd and zygote
     mkdir /dev/memcg/apps/ 0755 system system
+    # cgroup for system_server and surfaceflinger
+    mkdir /dev/memcg/system 0550 system system
 
     start ueventd