summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSim Sun <sunsj1231@gmail.com>2020-03-26 16:59:29 -0700
committerGitHub <noreply@github.com>2020-03-26 16:59:29 -0700
commit2157664745ddff0d34e8b0d620d14e0912f4296d (patch)
tree9b7d1bb324aa81e0e0687816e7fe30fca194d4bc
parent6382d6f5c9d4d149989e47b20446f794365137c1 (diff)
downloadlibunwind-2157664745ddff0d34e8b0d620d14e0912f4296d.tar.gz
arm: clear ip thumb/arm mode bit before move to previous instruction (#131)
-rw-r--r--src/arm/Gstep.c3
-rw-r--r--src/dwarf/Gparser.c9
-rw-r--r--src/mi/Gget_proc_name.c10
3 files changed, 19 insertions, 3 deletions
diff --git a/src/arm/Gstep.c b/src/arm/Gstep.c
index adec02e0..895e8a89 100644
--- a/src/arm/Gstep.c
+++ b/src/arm/Gstep.c
@@ -46,7 +46,8 @@ arm_exidx_step (struct cursor *c)
c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC;
unw_word_t ip = c->dwarf.ip;
if (c->dwarf.use_prev_instr)
- --ip;
+ /* The least bit denotes thumb/arm mode, clear it. */
+ ip = (ip & ~(unw_word_t)0x1) - 1;
/* check dynamic info first --- it overrides everything else */
ret = unwi_find_dynamic_proc_info (c->dwarf.as, ip, &c->dwarf.pi, 1,
diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c
index fe7c5817..28fd73c6 100644
--- a/src/dwarf/Gparser.c
+++ b/src/dwarf/Gparser.c
@@ -440,8 +440,15 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip)
continue, and it's important we get this right, as 'ip' could be
right at the function entry and hence FDE edge, or at instruction
that manipulates CFA (push/pop). */
+
if (c->use_prev_instr)
- --ip;
+ {
+#if defined(__arm__)
+ /* On arm, the least bit denotes thumb/arm mode, clear it. */
+ ip &= ~(unw_word_t)0x1;
+#endif
+ --ip;
+ }
memset (&c->pi, 0, sizeof (c->pi));
diff --git a/src/mi/Gget_proc_name.c b/src/mi/Gget_proc_name.c
index 840d9007..0b77fa59 100644
--- a/src/mi/Gget_proc_name.c
+++ b/src/mi/Gget_proc_name.c
@@ -106,7 +106,15 @@ unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len,
ip = tdep_get_ip (c);
#if !defined(__ia64__)
if (c->dwarf.use_prev_instr)
- --ip;
+ {
+#if defined(__arm__)
+ /* On arm, the least bit denotes thumb/arm mode, clear it. */
+ ip &= ~(unw_word_t)0x1;
+#endif
+ --ip;
+ }
+
+
#endif
error = get_proc_name (tdep_get_as (c), ip, buf, buf_len, offp,
tdep_get_as_arg (c));