diff options
author | Sim Sun <sunsj1231@gmail.com> | 2020-03-26 16:59:29 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-26 16:59:29 -0700 |
commit | 2157664745ddff0d34e8b0d620d14e0912f4296d (patch) | |
tree | 9b7d1bb324aa81e0e0687816e7fe30fca194d4bc | |
parent | 6382d6f5c9d4d149989e47b20446f794365137c1 (diff) | |
download | libunwind-2157664745ddff0d34e8b0d620d14e0912f4296d.tar.gz |
arm: clear ip thumb/arm mode bit before move to previous instruction (#131)
-rw-r--r-- | src/arm/Gstep.c | 3 | ||||
-rw-r--r-- | src/dwarf/Gparser.c | 9 | ||||
-rw-r--r-- | src/mi/Gget_proc_name.c | 10 |
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)); |