Add check for same ip/cfa.

Make sure that all of our supported architectures stop when the ip/cfa
does not change.

Bug: 20955299
Change-Id: Ic023c71439208ee5ef21efa0298ab7ed1ad03c00
(cherry picked from commit 2706ca232c0966b508003043f6a327ac8461e920)
diff --git a/src/aarch64/Gstep.c b/src/aarch64/Gstep.c
index fd1159d..3f5e8ad 100644
--- a/src/aarch64/Gstep.c
+++ b/src/aarch64/Gstep.c
@@ -112,6 +112,9 @@
   Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n",
 	 c, c->dwarf.ip, c->dwarf.cfa);
 
+  unw_word_t old_ip = c->dwarf.ip;
+  unw_word_t old_cfa = c->dwarf.cfa;
+
   /* Check if this is a signal frame. */
   if (unw_is_signal_frame (cursor))
     /* ANDROID support update. */
@@ -145,9 +148,17 @@
 
   if (ret >= 0)
     {
-      c->dwarf.frame++;
       if (c->dwarf.ip >= 4)
         c->dwarf.ip -= 4;
+      /* If the decode yields the exact same ip/cfa as before, then indicate
+         the unwind is complete. */
+      if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
+        {
+          Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
+                   __FUNCTION__, (long) c->dwarf.ip);
+          return -UNW_EBADFRAME;
+        }
+      c->dwarf.frame++;
     }
 
   if (unlikely (ret == -UNW_ESTOPUNWIND))
diff --git a/src/arm/Gstep.c b/src/arm/Gstep.c
index b5f2179..463edcd 100644
--- a/src/arm/Gstep.c
+++ b/src/arm/Gstep.c
@@ -35,13 +35,9 @@
 static inline int
 arm_exidx_step (struct cursor *c)
 {
-  unw_word_t old_ip, old_cfa;
   uint8_t buf[32];
   int ret;
 
-  old_ip = c->dwarf.ip;
-  old_cfa = c->dwarf.cfa;
-
   /* mark PC unsaved */
   c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC;
 
@@ -61,13 +57,6 @@
   if (ret < 0)
     return ret;
 
-  if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
-    {
-      Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
-	       __FUNCTION__, (long) c->dwarf.ip);
-      return -UNW_EBADFRAME;
-    }
-
   c->dwarf.pi_valid = 0;
 
   return (c->dwarf.ip == 0) ? 0 : 1;
@@ -208,6 +197,9 @@
 
   Debug (1, "(cursor=%p)\n", c);
 
+  unw_word_t old_ip = c->dwarf.ip;
+  unw_word_t old_cfa = c->dwarf.cfa;
+
   /* Check if this is a signal frame. */
   if (unw_is_signal_frame (cursor))
     {
@@ -320,8 +312,14 @@
 
   if (ret >= 0)
     {
-      c->dwarf.frame++;
       adjust_ip(c);
+      if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
+        {
+          Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
+                   __FUNCTION__, (long) c->dwarf.ip);
+          return -UNW_EBADFRAME;
+        }
+      c->dwarf.frame++;
     }
   return ret == -UNW_ENOINFO ? 0 : ret;
 }
diff --git a/src/mips/Gstep.c b/src/mips/Gstep.c
index f03273a..6521961 100644
--- a/src/mips/Gstep.c
+++ b/src/mips/Gstep.c
@@ -121,6 +121,9 @@
   struct cursor *c = (struct cursor *) cursor;
   int ret;
 
+  unw_word_t old_ip = c->dwarf.ip;
+  unw_word_t old_cfa = c->dwarf.cfa;
+
   ret = unw_handle_signal_frame (cursor);
   if (ret < 0)
     /* Not a signal frame, try DWARF-based unwinding. */
@@ -133,5 +136,14 @@
   if (unlikely (ret < 0))
     return 0;
 
+  /* If the decode yields the exact same ip/cfa as before, then indicate
+     the unwind is complete. */
+  if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
+    {
+      Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
+               __FUNCTION__, (long) c->dwarf.ip);
+      return -UNW_EBADFRAME;
+    }
+
   return (c->dwarf.ip == 0) ? 0 : 1;
 }
diff --git a/src/x86/Gstep.c b/src/x86/Gstep.c
index e2812aa..a1368eb 100644
--- a/src/x86/Gstep.c
+++ b/src/x86/Gstep.c
@@ -122,7 +122,11 @@
       /* If the decode yields the exact same ip/cfa as before, then indicate
          the unwind is complete. */
       if (old_ip == c->dwarf.ip && old_cfa == c->dwarf.cfa)
-        return 0;
+        {
+          Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
+                   __FUNCTION__, (long) c->dwarf.ip);
+          return -UNW_EBADFRAME;
+        }
       c->dwarf.frame++;
     }
   /* End of ANDROID update. */
diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c
index c965f99..87caf54 100644
--- a/src/x86_64/Gstep.c
+++ b/src/x86_64/Gstep.c
@@ -66,6 +66,9 @@
   Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n",
 	 c, c->dwarf.ip, c->dwarf.cfa);
 
+  unw_word_t old_ip = c->dwarf.ip;
+  unw_word_t old_cfa = c->dwarf.cfa;
+
   /* Try DWARF-based unwinding... */
   c->sigcontext_format = X86_64_SCF_NONE;
   ret = dwarf_step (&c->dwarf);
@@ -227,6 +230,14 @@
   /* Adjust the pc to the instruction before. */
   if (c->dwarf.ip)
     c->dwarf.ip--;
+  /* If the decode yields the exact same ip/cfa as before, then indicate
+     the unwind is complete. */
+  if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
+    {
+      Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
+               __FUNCTION__, (long) c->dwarf.ip);
+      return -UNW_EBADFRAME;
+    }
   /* End of ANDROID update. */
   Debug (2, "returning %d\n", ret);
   return ret;