summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMyungJoo Ham <myungjoo.ham@samsung.com>2016-05-19 02:52:09 +0000
committerDave Watson <davejwatson@fb.com>2017-08-15 10:34:09 -0700
commited90c8387b0c6ea2df69a90391e55c5f8c6eff29 (patch)
treeb7cb5916bf5edf1290200ab523ad4e35f5b05748
parentc4accd6ea2bd7893d44a2ffd253e972ab2c49099 (diff)
downloadlibunwind-ed90c8387b0c6ea2df69a90391e55c5f8c6eff29.tar.gz
arm: Fix is_signal_frame bug for Thumb/Thumb2 mode
If Thumb is used, the least bit of the retrived IP value is set, which makes the retrived opcode based on the IP invalid. This patch fixes such behavior and adds a missed condition found with glibc built for recent ARMv7l with Thumb2. Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> CC: Yvan Roux CC: Arun Sharma CC: David Mosberger
-rw-r--r--src/arm/Gis_signal_frame.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/arm/Gis_signal_frame.c b/src/arm/Gis_signal_frame.c
index e8efe7f4..bfae4c6b 100644
--- a/src/arm/Gis_signal_frame.c
+++ b/src/arm/Gis_signal_frame.c
@@ -44,6 +44,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/* Thumb sigreturn (two insns, syscall number is loaded into r7) */
#define THUMB_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_sigreturn)
#define THUMB_RT_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_rt_sigreturn)
+
+/* Thumb2 sigreturn (mov.w r7, $SYS_ify(rt_sigreturn/sigreturn)) */
+#define THUMB2_SIGRETURN (((0x0700 | ARM_NR_sigreturn) << 16) | \
+ 0xf04f)
+#define THUMB2_RT_SIGRETURN (((0x0700 | ARM_NR_rt_sigreturn) << 16) | \
+ 0xf04f)
+/* TODO: with different toolchains, there are a lot more possibilities */
#endif /* __linux__ */
/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal
@@ -63,17 +70,19 @@ unw_is_signal_frame (unw_cursor_t *cursor)
a = unw_get_accessors (as);
arg = c->dwarf.as_arg;
- ip = c->dwarf.ip;
+ /* The least bit denotes thumb/arm mode. Do not read there. */
+ ip = c->dwarf.ip & ~0x1;
if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0)
return ret;
/* Return 1 if the IP points to a non-RT sigreturn sequence. */
- if (w0 == MOV_R7_SIGRETURN || w0 == ARM_SIGRETURN || w0 == THUMB_SIGRETURN)
+ if (w0 == MOV_R7_SIGRETURN || w0 == ARM_SIGRETURN || w0 == THUMB_SIGRETURN
+ || w0 == THUMB2_SIGRETURN)
return 1;
/* Return 2 if the IP points to a RT sigreturn sequence. */
else if (w0 == MOV_R7_RT_SIGRETURN || w0 == ARM_RT_SIGRETURN
- || w0 == THUMB_RT_SIGRETURN)
+ || w0 == THUMB_RT_SIGRETURN || w0 == THUMB2_RT_SIGRETURN)
return 2;
return 0;