Reland "Android: Add helper methods for printing native stack traces"

This is a reland of dc32cc00e80972223767be339f9318b803f4a2ae

Relanding because this CL was not the culprit for the Chrome bot.
(This code shouldn't even be executed in Chrome).

Original change's description:
> Android: Add helper methods for printing native stack traces
>
> This CL adds utility functions to unwind the stack for a given thread on
> Android ARM devices. This works on top of unwind.h and unwinds native
> (C++) stack traces only. Unwinding a thread from another thread is done
> by overriding the signal handler with a custom function and then
> interrupting the specific thread.
>
> Bug: webrtc:10168
> Change-Id: If5adffd3a6bb57bf502168743e09a7eefc292bf3
> Reviewed-on: https://webrtc-review.googlesource.com/c/118141
> Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
> Reviewed-by: Tommi <tommi@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26328}

TBR=tommi

Bug: webrtc:10168
Change-Id: I4c33c2c147cf10c0172c98a55d32dd35a08517c8
Reviewed-on: https://webrtc-review.googlesource.com/c/118704
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26341}
diff --git a/sdk/android/native_unittests/stacktrace/stacktrace_unittest.cc b/sdk/android/native_unittests/stacktrace/stacktrace_unittest.cc
new file mode 100644
index 0000000..4268fda
--- /dev/null
+++ b/sdk/android/native_unittests/stacktrace/stacktrace_unittest.cc
@@ -0,0 +1,187 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "sdk/android/native_api/stacktrace/stacktrace.h"
+#include <dlfcn.h>
+#include <vector>
+#include "absl/memory/memory.h"
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/event.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/strings/string_builder.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace test {
+
+// Returns the execution address relative to the .so base address. This matches
+// the addresses we get from GetStacktrace().
+uint32_t GetCurrentRelativeExecutionAddress() {
+  void* pc = __builtin_return_address(0);
+  Dl_info dl_info = {};
+  const bool success = dladdr(pc, &dl_info);
+  EXPECT_TRUE(success);
+  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc) -
+                               reinterpret_cast<uintptr_t>(dl_info.dli_fbase));
+}
+
+// Returns true if any of the stack trace element is inside the specified
+// region.
+bool StackTraceContainsRange(const std::vector<StackTraceElement>& stack_trace,
+                             uintptr_t pc_low,
+                             uintptr_t pc_high) {
+  for (const StackTraceElement& stack_trace_element : stack_trace) {
+    if (pc_low <= stack_trace_element.relative_address &&
+        pc_high >= stack_trace_element.relative_address) {
+      return true;
+    }
+  }
+  return false;
+}
+
+class DeadlockInterface {
+ public:
+  virtual ~DeadlockInterface() {}
+
+  // This function should deadlock until Release() is called.
+  virtual void Deadlock() = 0;
+
+  // This function should release the thread stuck in Deadlock().
+  virtual void Release() = 0;
+};
+
+struct ThreadParams {
+  volatile int tid;
+  // Signaled when the deadlock region is entered.
+  rtc::Event deadlock_start_event;
+  DeadlockInterface* volatile deadlock_impl;
+  // Defines an address range within the deadlock will occur.
+  volatile uint32_t deadlock_region_start_address;
+  volatile uint32_t deadlock_region_end_address;
+  // Signaled when the deadlock is done.
+  rtc::Event deadlock_done_event;
+};
+
+class RtcEventDeadlock : public DeadlockInterface {
+ private:
+  void Deadlock() override { event.Wait(rtc::Event::kForever); }
+  void Release() override { event.Set(); }
+
+  rtc::Event event;
+};
+
+class RtcCriticalSectionDeadlock : public DeadlockInterface {
+ public:
+  RtcCriticalSectionDeadlock()
+      : critscope_(absl::make_unique<rtc::CritScope>(&crit_)) {}
+
+ private:
+  void Deadlock() override { rtc::CritScope lock(&crit_); }
+
+  void Release() override { critscope_.reset(); }
+
+  rtc::CriticalSection crit_;
+  std::unique_ptr<rtc::CritScope> critscope_;
+};
+
+class SpinDeadlock : public DeadlockInterface {
+ public:
+  SpinDeadlock() : is_deadlocked_(true) {}
+
+ private:
+  void Deadlock() override {
+    while (is_deadlocked_) {
+    }
+  }
+
+  void Release() override { is_deadlocked_ = false; }
+
+  std::atomic<bool> is_deadlocked_;
+};
+
+class SleepDeadlock : public DeadlockInterface {
+ private:
+  void Deadlock() override { sleep(1000000); }
+
+  void Release() override {
+    // The interrupt itself will break free from the sleep.
+  }
+};
+
+// This is the function that is exectued by the thread that will deadlock and
+// have its stacktrace captured.
+void ThreadFunction(void* void_params) {
+  ThreadParams* params = static_cast<ThreadParams*>(void_params);
+  params->tid = gettid();
+
+  params->deadlock_region_start_address = GetCurrentRelativeExecutionAddress();
+  params->deadlock_start_event.Set();
+  params->deadlock_impl->Deadlock();
+  params->deadlock_region_end_address = GetCurrentRelativeExecutionAddress();
+
+  params->deadlock_done_event.Set();
+}
+
+void TestStacktrace(std::unique_ptr<DeadlockInterface> deadlock_impl) {
+  // Set params that will be sent to other thread.
+  ThreadParams params;
+  params.deadlock_impl = deadlock_impl.get();
+
+  // Spawn thread.
+  rtc::PlatformThread thread(&ThreadFunction, &params, "StacktraceTest");
+  thread.Start();
+
+  // Wait until the thread has entered the deadlock region.
+  params.deadlock_start_event.Wait(rtc::Event::kForever);
+
+  // Acquire the stack trace of the thread which should now be deadlocking.
+  std::vector<StackTraceElement> stack_trace = GetStackTrace(params.tid);
+
+  // Release the deadlock so that the thread can continue.
+  deadlock_impl->Release();
+
+  // Wait until the thread has left the deadlock.
+  params.deadlock_done_event.Wait(rtc::Event::kForever);
+
+  // Assert that the stack trace contains the deadlock region.
+  EXPECT_TRUE(StackTraceContainsRange(stack_trace,
+                                      params.deadlock_region_start_address,
+                                      params.deadlock_region_end_address))
+      << "Deadlock region: ["
+      << rtc::ToHex(params.deadlock_region_start_address) << ", "
+      << rtc::ToHex(params.deadlock_region_end_address)
+      << "] not contained in: " << StackTraceToString(stack_trace);
+
+  thread.Stop();
+}
+
+TEST(Stacktrace, TestSpinLock) {
+  TestStacktrace(absl::make_unique<SpinDeadlock>());
+}
+
+TEST(Stacktrace, TestSleep) {
+  TestStacktrace(absl::make_unique<SleepDeadlock>());
+}
+
+// Stack traces originating from kernel space does not include user space stack
+// traces for ARM 32.
+#ifdef WEBRTC_ARCH_ARM64
+TEST(Stacktrace, TestRtcEvent) {
+  TestStacktrace(absl::make_unique<RtcEventDeadlock>());
+}
+
+TEST(Stacktrace, TestRtcCriticalSection) {
+  TestStacktrace(absl::make_unique<RtcCriticalSectionDeadlock>());
+}
+#endif
+
+}  // namespace test
+}  // namespace webrtc