More libbacktrace fixes.

Included in minor fix ups is the addition of a warning macro to replace
all of the ALOGW calls.

Fix a race where multiple threads could be attempting to unwind the threads
of the current process at the same time.

Bug: 8410085

Change-Id: I02a65dc778dde690e5f95fc8ff069a32d0832fd1
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index eca1c3d..17d9e1d 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -72,10 +72,8 @@
   return impl_->Unwind(num_ignore_frames);
 }
 
-__BEGIN_DECLS
-extern char* __cxa_demangle (const char* mangled, char* buf, size_t* len,
-                             int* status);
-__END_DECLS
+extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len,
+                                int* status);
 
 std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
   std::string func_name = impl_->GetFunctionNameRaw(pc, offset);
@@ -97,7 +95,7 @@
 
 bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value) {
   if (ptr & 3) {
-    ALOGW("Backtrace::verifyReadWordArgs: invalid pointer %p", (void*)ptr);
+    BACK_LOGW("invalid pointer %p", (void*)ptr);
     *out_value = (uint32_t)-1;
     return false;
   }
@@ -172,7 +170,7 @@
     *out_value = *reinterpret_cast<uint32_t*>(ptr);
     return true;
   } else {
-    ALOGW("BacktraceCurrent::readWord: pointer %p not in a readbale map", reinterpret_cast<void*>(ptr));
+    BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr));
     *out_value = static_cast<uint32_t>(-1);
     return false;
   }
@@ -198,7 +196,7 @@
   }
 
 #if defined(__APPLE__)
-  ALOGW("BacktracePtrace::readWord: MacOS does not support reading from another pid.\n");
+  BACK_LOGW("MacOS does not support reading from another pid.");
   return false;
 #else
   // ptrace() returns -1 and sets errno when the operation fails.
@@ -206,8 +204,8 @@
   errno = 0;
   *out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL);
   if (*out_value == static_cast<uint32_t>(-1) && errno) {
-    ALOGW("BacktracePtrace::readWord: invalid pointer 0x%08x reading from tid %d, "
-          "ptrace() errno=%d", ptr, Tid(), errno);
+    BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
+              reinterpret_cast<void*>(ptr), Tid(), strerror(errno));
     return false;
   }
   return true;
@@ -295,11 +293,8 @@
     const backtrace_context_t* context, size_t frame_num, char* buf,
     size_t buf_size) {
   if (buf_size == 0 || buf == NULL) {
-    ALOGW("backtrace_format_frame_data: bad call buf %p buf_size %zu\n",
-          buf, buf_size);
-    return;
-  }
-  if (context->data) {
+    BACK_LOGW("bad call buf %p buf_size %zu", buf, buf_size);
+  } else if (context->data) {
     Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
     std::string line = backtrace->FormatFrameData(frame_num);
     if (line.size() > buf_size) {
diff --git a/libbacktrace/Backtrace.h b/libbacktrace/Backtrace.h
index b89bc89..00f0a10 100644
--- a/libbacktrace/Backtrace.h
+++ b/libbacktrace/Backtrace.h
@@ -21,6 +21,10 @@
 
 #include <sys/types.h>
 
+// Macro to log the function name along with the warning message.
+#define BACK_LOGW(format, ...) \
+  ALOGW("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__)
+
 class BacktraceImpl {
 public:
   virtual ~BacktraceImpl() { }
diff --git a/libbacktrace/BacktraceThread.cpp b/libbacktrace/BacktraceThread.cpp
index 6c3641e..8e664c4 100644
--- a/libbacktrace/BacktraceThread.cpp
+++ b/libbacktrace/BacktraceThread.cpp
@@ -31,55 +31,55 @@
 // ThreadEntry implementation.
 //-------------------------------------------------------------------------
 static ThreadEntry* g_list = NULL;
-static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t g_entry_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 ThreadEntry::ThreadEntry(
     BacktraceThreadInterface* intf, pid_t pid, pid_t tid, size_t num_ignore_frames)
-    : thread_intf_(intf), pid_(pid), tid_(tid), next_(NULL), prev_(NULL),
-      state_(STATE_WAITING), num_ignore_frames_(num_ignore_frames) {
+    : thread_intf(intf), pid(pid), tid(tid), next(NULL), prev(NULL),
+      state(STATE_WAITING), num_ignore_frames(num_ignore_frames) {
 }
 
 ThreadEntry::~ThreadEntry() {
-  pthread_mutex_lock(&g_mutex);
+  pthread_mutex_lock(&g_entry_mutex);
   if (g_list == this) {
-    g_list = next_;
+    g_list = next;
   } else {
-    if (next_) {
-      next_->prev_ = prev_;
+    if (next) {
+      next->prev = prev;
     }
-    prev_->next_ = next_;
+    prev->next = next;
   }
-  pthread_mutex_unlock(&g_mutex);
+  pthread_mutex_unlock(&g_entry_mutex);
 
-  next_ = NULL;
-  prev_ = NULL;
+  next = NULL;
+  prev = NULL;
 }
 
 ThreadEntry* ThreadEntry::AddThreadToUnwind(
     BacktraceThreadInterface* intf, pid_t pid, pid_t tid, size_t num_ignore_frames) {
   ThreadEntry* entry = new ThreadEntry(intf, pid, tid, num_ignore_frames);
 
-  pthread_mutex_lock(&g_mutex);
+  pthread_mutex_lock(&g_entry_mutex);
   ThreadEntry* cur_entry = g_list;
   while (cur_entry != NULL) {
     if (cur_entry->Match(pid, tid)) {
       // There is already an entry for this pid/tid, this is bad.
-      ALOGW("%s::%s(): Entry for pid %d tid %d already exists.\n",
-            __FILE__, __FUNCTION__, pid, tid);
+      BACK_LOGW("Entry for pid %d tid %d already exists.", pid, tid);
 
-      pthread_mutex_unlock(&g_mutex);
+      pthread_mutex_unlock(&g_entry_mutex);
       return NULL;
     }
-    cur_entry = cur_entry->next_;
+    cur_entry = cur_entry->next;
   }
 
   // Add the entry to the list.
-  entry->next_ = g_list;
+  entry->next = g_list;
   if (g_list) {
-    g_list->prev_ = entry;
+    g_list->prev = entry;
   }
   g_list = entry;
-  pthread_mutex_unlock(&g_mutex);
+  pthread_mutex_unlock(&g_entry_mutex);
 
   return entry;
 }
@@ -89,7 +89,7 @@
 //-------------------------------------------------------------------------
 static void SignalHandler(int n __attribute__((unused)), siginfo_t* siginfo,
                           void* sigcontext) {
-  if (pthread_mutex_lock(&g_mutex) == 0) {
+  if (pthread_mutex_lock(&g_entry_mutex) == 0) {
     pid_t pid = getpid();
     pid_t tid = gettid();
     ThreadEntry* cur_entry = g_list;
@@ -97,20 +97,19 @@
       if (cur_entry->Match(pid, tid)) {
         break;
       }
-      cur_entry = cur_entry->next_;
+      cur_entry = cur_entry->next;
     }
-    pthread_mutex_unlock(&g_mutex);
+    pthread_mutex_unlock(&g_entry_mutex);
     if (!cur_entry) {
-      ALOGW("%s::%s(): Unable to find pid %d tid %d information\n",
-            __FILE__, __FUNCTION__, pid, tid);
+      BACK_LOGW("Unable to find pid %d tid %d information", pid, tid);
       return;
     }
 
-    if (android_atomic_acquire_cas(STATE_WAITING, STATE_DUMPING, &cur_entry->state_) == 0) {
-      cur_entry->thread_intf_->ThreadUnwind(siginfo, sigcontext,
-                                            cur_entry->num_ignore_frames_);
+    if (android_atomic_acquire_cas(STATE_WAITING, STATE_DUMPING, &cur_entry->state) == 0) {
+      cur_entry->thread_intf->ThreadUnwind(siginfo, sigcontext,
+                                           cur_entry->num_ignore_frames);
     }
-    android_atomic_release_store(STATE_DONE, &cur_entry->state_);
+    android_atomic_release_store(STATE_DONE, &cur_entry->state);
   }
 }
 
@@ -143,18 +142,18 @@
 }
 
 bool BacktraceThread::TriggerUnwindOnThread(ThreadEntry* entry) {
-  entry->state_ = STATE_WAITING;
+  entry->state = STATE_WAITING;
 
   if (tgkill(Pid(), Tid(), SIGURG) != 0) {
-    ALOGW("%s::%s(): tgkill failed %s\n", __FILE__, __FUNCTION__, strerror(errno));
+    BACK_LOGW("tgkill failed %s", strerror(errno));
     return false;
   }
 
-  // Allow up to a second for the dump to occur.
-  int wait_millis = 1000;
+  // Allow up to ten seconds for the dump to start.
+  int wait_millis = 10000;
   int32_t state;
   while (true) {
-    state = android_atomic_acquire_load(&entry->state_);
+    state = android_atomic_acquire_load(&entry->state);
     if (state != STATE_WAITING) {
       break;
     }
@@ -167,24 +166,22 @@
 
   bool cancelled = false;
   if (state == STATE_WAITING) {
-    if (android_atomic_acquire_cas(state, STATE_CANCEL, &entry->state_) == 0) {
-      ALOGW("%s::%s(): Cancelled dump of thread %d\n", __FILE__, __FUNCTION__,
-            entry->tid_);
+    if (android_atomic_acquire_cas(state, STATE_CANCEL, &entry->state) == 0) {
+      BACK_LOGW("Cancelled dump of thread %d", entry->tid);
       state = STATE_CANCEL;
       cancelled = true;
     } else {
-      state = android_atomic_acquire_load(&entry->state_);
+      state = android_atomic_acquire_load(&entry->state);
     }
   }
 
-  // Wait for at most one minute for the dump to finish.
-  wait_millis = 60000;
-  while (android_atomic_acquire_load(&entry->state_) != STATE_DONE) {
+  // Wait for at most ten seconds for the cancel or dump to finish.
+  wait_millis = 10000;
+  while (android_atomic_acquire_load(&entry->state) != STATE_DONE) {
     if (wait_millis--) {
       usleep(1000);
     } else {
-      ALOGW("%s::%s(): Didn't finish thread unwind in 60 seconds.\n",
-            __FILE__, __FUNCTION__);
+      BACK_LOGW("Didn't finish thread unwind in 60 seconds.");
       break;
     }
   }
@@ -202,17 +199,24 @@
     return false;
   }
 
+  // Prevent multiple threads trying to set the trigger action on different
+  // threads at the same time.
   bool retval = false;
-  struct sigaction act, oldact;
-  memset(&act, 0, sizeof(act));
-  act.sa_sigaction = SignalHandler;
-  act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
-  sigemptyset(&act.sa_mask);
-  if (sigaction(SIGURG, &act, &oldact) == 0) {
-    retval = TriggerUnwindOnThread(entry);
-    sigaction(SIGURG, &oldact, NULL);
+  if (pthread_mutex_lock(&g_sigaction_mutex) == 0) {
+    struct sigaction act, oldact;
+    memset(&act, 0, sizeof(act));
+    act.sa_sigaction = SignalHandler;
+    act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+    sigemptyset(&act.sa_mask);
+    if (sigaction(SIGURG, &act, &oldact) == 0) {
+      retval = TriggerUnwindOnThread(entry);
+      sigaction(SIGURG, &oldact, NULL);
+    } else {
+      BACK_LOGW("sigaction failed %s", strerror(errno));
+    }
+    pthread_mutex_unlock(&g_sigaction_mutex);
   } else {
-    ALOGW("%s::%s(): sigaction failed %s\n", __FILE__, __FUNCTION__, strerror(errno));
+    BACK_LOGW("unable to acquire sigaction mutex.");
   }
 
   if (retval) {
diff --git a/libbacktrace/BacktraceThread.h b/libbacktrace/BacktraceThread.h
index afea771..8ed1122 100644
--- a/libbacktrace/BacktraceThread.h
+++ b/libbacktrace/BacktraceThread.h
@@ -32,26 +32,25 @@
 
 class BacktraceThreadInterface;
 
-class ThreadEntry {
-public:
+struct ThreadEntry {
   ThreadEntry(
       BacktraceThreadInterface* impl, pid_t pid, pid_t tid,
       size_t num_ignore_frames);
   ~ThreadEntry();
 
-  bool Match(pid_t pid, pid_t tid) { return (pid == pid_ && tid == tid_); }
+  bool Match(pid_t chk_pid, pid_t chk_tid) { return (chk_pid == pid && chk_tid == tid); }
 
   static ThreadEntry* AddThreadToUnwind(
       BacktraceThreadInterface* thread_intf, pid_t pid, pid_t tid,
       size_t num_ignored_frames);
 
-  BacktraceThreadInterface* thread_intf_;
-  pid_t pid_;
-  pid_t tid_;
-  ThreadEntry* next_;
-  ThreadEntry* prev_;
-  int32_t state_;
-  int num_ignore_frames_;
+  BacktraceThreadInterface* thread_intf;
+  pid_t pid;
+  pid_t tid;
+  ThreadEntry* next;
+  ThreadEntry* prev;
+  int32_t state;
+  int num_ignore_frames;
 };
 
 // Interface class that does not contain any local storage, only defines
diff --git a/libbacktrace/Corkscrew.cpp b/libbacktrace/Corkscrew.cpp
index 8ba1e80..9daa752 100644
--- a/libbacktrace/Corkscrew.cpp
+++ b/libbacktrace/Corkscrew.cpp
@@ -37,7 +37,7 @@
 bool CorkscrewCommon::GenerateFrameData(
     backtrace_frame_t* cork_frames, ssize_t num_frames) {
   if (num_frames < 0) {
-    ALOGW("CorkscrewCommon::GenerateFrameData: libcorkscrew unwind failed.\n");
+    BACK_LOGW("libcorkscrew unwind failed.");
     return false;
   }
 
@@ -184,7 +184,7 @@
 }
 
 //-------------------------------------------------------------------------
-// C++ object createion functions.
+// C++ object creation functions.
 //-------------------------------------------------------------------------
 Backtrace* CreateCurrentObj() {
   return new BacktraceCurrent(new CorkscrewCurrent());
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
index 0280e93..d4ba68f 100644
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -27,9 +27,9 @@
 
 #include "UnwindCurrent.h"
 
+// Define the ucontext_t structures needed for each supported arch.
 #if defined(__arm__)
-  #if !defined(__BIONIC_HAVE_UCONTEXT_T)
-  // The Current version of the Android <signal.h> doesn't define ucontext_t.
+  // The current version of the <signal.h> doesn't define ucontext_t.
   #include <asm/sigcontext.h> // Ensure 'struct sigcontext' is defined.
 
   // Machine context at the time a signal was raised.
@@ -40,8 +40,19 @@
     struct sigcontext uc_mcontext;
     uint32_t uc_sigmask;
   } ucontext_t;
-  #endif // !__BIONIC_HAVE_UCONTEXT_T
-#endif // defined(__arm__)
+#elif defined(__mips__)
+  typedef struct ucontext {
+    uint32_t sp;
+    uint32_t ra;
+    uint32_t pc;
+  } ucontext_t;
+#elif defined(__i386__)
+  #include <asm/sigcontext.h>
+  #include <asm/ucontext.h>
+  typedef struct ucontext ucontext_t;
+#else
+  #error Unsupported architecture.
+#endif
 
 //-------------------------------------------------------------------------
 // UnwindCurrent functions.
@@ -55,7 +66,7 @@
 bool UnwindCurrent::Unwind(size_t num_ignore_frames) {
   int ret = unw_getcontext(&context_);
   if (ret < 0) {
-    ALOGW("UnwindCurrent::Unwind: unw_getcontext failed %d\n", ret);
+    BACK_LOGW("unw_getcontext failed %d", ret);
     return false;
   }
   return UnwindFromContext(num_ignore_frames, true);
@@ -81,7 +92,7 @@
   unw_cursor_t* cursor = new unw_cursor_t;
   int ret = unw_init_local(cursor, &context_);
   if (ret < 0) {
-    ALOGW("UnwindCurrent::UnwindWithContext: unw_init_local failed %d\n", ret);
+    BACK_LOGW("unw_init_local failed %d", ret);
     return false;
   }
 
@@ -89,13 +100,13 @@
     unw_word_t pc;
     ret = unw_get_reg(cursor, UNW_REG_IP, &pc);
     if (ret < 0) {
-      ALOGW("UnwindCurrent::UnwindWithContext: Failed to read IP %d\n", ret);
+      BACK_LOGW("Failed to read IP %d", ret);
       break;
     }
     unw_word_t sp;
     ret = unw_get_reg(cursor, UNW_REG_SP, &sp);
     if (ret < 0) {
-      ALOGW("UnwindCurrent::UnwindWithContext: Failed to read SP %d\n", ret);
+      BACK_LOGW("Failed to read SP %d", ret);
       break;
     }
 
@@ -142,10 +153,9 @@
 
 void UnwindCurrent::ExtractContext(void* sigcontext) {
   unw_tdep_context_t* context = reinterpret_cast<unw_tdep_context_t*>(&context_);
-
-#if defined(__arm__)
   const ucontext_t* uc = reinterpret_cast<const ucontext_t*>(sigcontext);
 
+#if defined(__arm__)
   context->regs[0] = uc->uc_mcontext.arm_r0;
   context->regs[1] = uc->uc_mcontext.arm_r1;
   context->regs[2] = uc->uc_mcontext.arm_r2;
@@ -162,28 +172,11 @@
   context->regs[13] = uc->uc_mcontext.arm_sp;
   context->regs[14] = uc->uc_mcontext.arm_lr;
   context->regs[15] = uc->uc_mcontext.arm_pc;
-
 #elif defined(__mips__)
-
-  typedef struct ucontext {
-    uint32_t sp;
-    uint32_t ra;
-    uint32_t pc;
-  } ucontext_t;
-
-  const ucontext_t* uc = (const ucontext_t*)sigcontext;
-
   context->uc_mcontext.sp = uc->sp;
   context->uc_mcontext.pc = uc->pc;
   context->uc_mcontext.ra = uc->ra;
-#elif defined(__x86__)
-
-  #include <asm/sigcontext.h>
-  #include <asm/ucontext.h>
-  typedef struct ucontext ucontext_t;
-
-  const ucontext_t* uc = (const ucontext_t*)sigcontext;
-
+#elif defined(__i386__)
   context->uc_mcontext.gregs[REG_EBP] = uc->uc_mcontext.gregs[REG_EBP];
   context->uc_mcontext.gregs[REG_ESP] = uc->uc_mcontext.gregs[REG_ESP];
   context->uc_mcontext.gregs[REG_EIP] = uc->uc_mcontext.gregs[REG_EIP];
diff --git a/libbacktrace/UnwindPtrace.cpp b/libbacktrace/UnwindPtrace.cpp
index 628caa0..a734a24 100644
--- a/libbacktrace/UnwindPtrace.cpp
+++ b/libbacktrace/UnwindPtrace.cpp
@@ -45,13 +45,13 @@
 bool UnwindPtrace::Unwind(size_t num_ignore_frames) {
   addr_space_ = unw_create_addr_space(&_UPT_accessors, 0);
   if (!addr_space_) {
-    ALOGW("UnwindPtrace::Unwind: unw_create_addr_space failed.\n");
+    BACK_LOGW("unw_create_addr_space failed.");
     return false;
   }
 
   upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(backtrace_obj_->Tid()));
   if (!upt_info_) {
-    ALOGW("UnwindPtrace::Unwind: Failed to create upt info.\n");
+    BACK_LOGW("Failed to create upt info.");
     return false;
   }
 
@@ -61,7 +61,7 @@
   unw_cursor_t cursor;
   int ret = unw_init_remote(&cursor, addr_space_, upt_info_);
   if (ret < 0) {
-    ALOGW("UnwindPtrace::Unwind: unw_init_remote failed %d\n", ret);
+    BACK_LOGW("unw_init_remote failed %d", ret);
     return false;
   }
 
@@ -69,13 +69,13 @@
     unw_word_t pc;
     ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
     if (ret < 0) {
-      ALOGW("UnwindPtrace::Unwind: Failed to read IP %d\n", ret);
+      BACK_LOGW("Failed to read IP %d", ret);
       break;
     }
     unw_word_t sp;
     ret = unw_get_reg(&cursor, UNW_REG_SP, &sp);
     if (ret < 0) {
-      ALOGW("UnwindPtrace::Unwind: Failed to read SP %d\n", ret);
+      BACK_LOGW("Failed to read SP %d", ret);
       break;
     }