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;