Merge tag android-5.1.0_r1 into AOSP_5.1_MERGE

Change-Id: I2dd6a87b4a5ea59e4f04b4bd2c094500bdeae0d8
diff --git a/src/Los-common.c b/src/Los-common.c
index cad43d0..d8f57e3 100644
--- a/src/Los-common.c
+++ b/src/Los-common.c
@@ -30,10 +30,18 @@
 extern struct map_info *local_map_list;
 extern lock_rdwr_var (local_rdwr_lock);
 
+static pthread_once_t local_rdwr_lock_init = PTHREAD_ONCE_INIT;
+
+static void
+map_local_init_once (void)
+{
+  lock_rdwr_init (&local_rdwr_lock);
+}
+
 HIDDEN void
 map_local_init (void)
 {
-  lock_rdwr_init (&local_rdwr_lock);
+  pthread_once (&local_rdwr_lock_init, map_local_init_once);
 }
 
 static void
diff --git a/src/aarch64/Gis_signal_frame.c b/src/aarch64/Gis_signal_frame.c
index 53e32de..d1ba021 100644
--- a/src/aarch64/Gis_signal_frame.c
+++ b/src/aarch64/Gis_signal_frame.c
@@ -47,10 +47,16 @@
   arg = c->dwarf.as_arg;
 
   ip = c->dwarf.ip;
+  /* ANDROID support update. */
+  /* Undo the attempt to correct the PC or we'll be pointing to the nop instead of the mov. */
+  ip += 4;
+  /* ANDROID support update. */
 
   ret = (*a->access_mem) (as, ip, &w0, 0, arg);
   if (ret < 0)
-    return ret;
+  /* ANDROID support update. */
+    return 0;
+  /* End ANDROID update. */
 
   /* FIXME: distinguish 32bit insn vs 64bit registers.  */
   if (w0 != 0xd4000001d2801168)
diff --git a/src/aarch64/Gstep.c b/src/aarch64/Gstep.c
index 8a517fd..fd1159d 100644
--- a/src/aarch64/Gstep.c
+++ b/src/aarch64/Gstep.c
@@ -107,17 +107,41 @@
 unw_step (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
-  int ret;
+  int ret = -UNW_ENOINFO;
 
   Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n",
 	 c, c->dwarf.ip, c->dwarf.cfa);
 
   /* Check if this is a signal frame. */
   if (unw_is_signal_frame (cursor))
-    return unw_handle_signal_frame (cursor);
+    /* ANDROID support update. */
+    ret = unw_handle_signal_frame (cursor);
+    /* End ANDROID update. */
 
-  ret = dwarf_step (&c->dwarf);
-  Debug(1, "dwarf_step()=%d\n", ret);
+  /* ANDROID support update. */
+  if (ret < 0)
+    {
+      ret = dwarf_step (&c->dwarf);
+      Debug(1, "dwarf_step()=%d\n", ret);
+    }
+
+  if (ret < 0 && c->dwarf.frame == 0)
+    {
+      /* If this is the first frame, the code may be executing garbage
+       * in the middle of nowhere. In this case, try using the lr as
+       * the pc.
+       */
+      unw_word_t lr;
+      if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_AARCH64_X30], &lr) >= 0)
+        {
+          if (lr != c->dwarf.ip)
+            {
+              ret = 1;
+              c->dwarf.ip = lr;
+            }
+        }
+    }
+  /* End ANDROID update. */
 
   if (ret >= 0)
     {
diff --git a/src/arm/Gis_signal_frame.c b/src/arm/Gis_signal_frame.c
index e8efe7f..4126de9 100644
--- a/src/arm/Gis_signal_frame.c
+++ b/src/arm/Gis_signal_frame.c
@@ -66,7 +66,9 @@
   ip = c->dwarf.ip;
 
   if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
-    return ret;
+  /* ANDROID support update. */
+    return 0;
+  /* End ANDROID update. */
 
   /* Return 1 if the IP points to a non-RT sigreturn sequence.  */
   if (w0 == MOV_R7_SIGRETURN || w0 == ARM_SIGRETURN || w0 == THUMB_SIGRETURN)
diff --git a/src/mi/Lmap.c b/src/mi/Lmap.c
index e07a50a..ba93ab9 100644
--- a/src/mi/Lmap.c
+++ b/src/mi/Lmap.c
@@ -36,6 +36,10 @@
 {
   intrmask_t saved_mask;
 
+  /* This function can be called before any other unwind code, so make sure
+     the lock has been initialized.  */
+  map_local_init ();
+
   lock_rdwr_wr_acquire (&local_rdwr_lock, saved_mask);
   map_cursor->map_list = local_map_list;
   map_cursor->cur_map = local_map_list;
@@ -56,6 +60,10 @@
   intrmask_t saved_mask;
   int ret_value = 0;
 
+  /* This function can be called before any other unwind code, so make sure
+     the lock has been initialized.  */
+  map_local_init ();
+
   lock_rdwr_wr_acquire (&local_rdwr_lock, saved_mask);
   if (local_map_list_refs == 0)
     {
@@ -76,6 +84,10 @@
 {
   intrmask_t saved_mask;
 
+  /* This function can be called before any other unwind code, so make sure
+     the lock has been initialized.  */
+  map_local_init ();
+
   lock_rdwr_wr_acquire (&local_rdwr_lock, saved_mask);
   if (local_map_list != NULL && --local_map_list_refs == 0)
     {
@@ -95,6 +107,10 @@
   if (map_info == NULL)
     return 0;
 
+  /* This function can be called before any other unwind code, so make sure
+     the lock has been initialized.  */
+  map_local_init ();
+
   lock_rdwr_rd_acquire (&local_rdwr_lock, saved_mask);
   if (map_cursor->map_list != local_map_list)
     {