[Crash-utility] [PATCH] arm64: support compat user mode prstatus

Andrew Jones drjones at redhat.com
Fri Dec 18 22:55:07 UTC 2015


compat user mode prstatus already just works, almost. This missing
pieces are that pt_regs->sp and pt_regs->fp are not in their usual
locations. We need to pull them out of their architecturally mapped
general purpose registers.
---
 arm64.c | 42 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/arm64.c b/arm64.c
index 183e768498fe8..3a82d20cdd465 100644
--- a/arm64.c
+++ b/arm64.c
@@ -993,6 +993,25 @@ arm64_stackframe_init(void)
 #define PSR_MODE_EL3h   0x0000000d
 #define PSR_MODE_MASK   0x0000000f
 
+/* Architecturally defined mapping between AArch32 and AArch64 registers */
+#define compat_usr(x)   regs[(x)]
+#define compat_fp       regs[11]
+#define compat_sp       regs[13]
+#define compat_lr       regs[14]
+
+#define user_mode(ptregs) \
+	(((ptregs)->pstate & PSR_MODE_MASK) == PSR_MODE_EL0t)
+
+#define compat_user_mode(ptregs)  \
+	(((ptregs)->pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) == \
+	 (PSR_MODE32_BIT | PSR_MODE_EL0t))
+
+#define user_stack_pointer(ptregs) \
+	(!compat_user_mode(ptregs) ? (ptregs)->sp : (ptregs)->compat_sp)
+
+#define user_frame_pointer(ptregs) \
+	(!compat_user_mode(ptregs) ? (ptregs)->regs[29] : (ptregs)->compat_fp)
+
 static int
 arm64_is_kernel_exception_frame(struct bt_info *bt, ulong stkptr)
 {
@@ -1340,21 +1359,28 @@ arm64_get_dumpfile_stackframe(struct bt_info *bt, struct arm64_stackframe *frame
 	struct machine_specific *ms = machdep->machspec;
 	struct arm64_pt_regs *ptregs;
 
-	if (!ms->panic_task_regs ||
-	    (!ms->panic_task_regs[bt->tc->processor].sp && 
-	     !ms->panic_task_regs[bt->tc->processor].pc)) {
+	if (!ms->panic_task_regs || !ms->panic_task_regs[bt->tc->processor].pc) {
 		bt->flags |= BT_REGS_NOT_FOUND;
 		return FALSE;
 	}
 
 	ptregs = &ms->panic_task_regs[bt->tc->processor];
-	frame->sp = ptregs->sp;
 	frame->pc = ptregs->pc;
-	frame->fp = ptregs->regs[29];
-
-	if (!is_kernel_text(frame->pc) && 
-	    in_user_stack(bt->tc->task, frame->sp))
+	if (user_mode(ptregs)) {
+		frame->sp = user_stack_pointer(ptregs);
+		frame->fp = user_frame_pointer(ptregs);
+		if (is_kernel_text(frame->pc) ||
+		    !in_user_stack(bt->tc->task, frame->sp)) {
+			error(WARNING, "Corrupt prstatus? pstate=0x%lx, but no user frame found\n",
+										ptregs->pstate);
+			bt->flags |= BT_REGS_NOT_FOUND;
+			return FALSE;
+		}
 		bt->flags |= BT_USER_SPACE;
+	} else {
+		frame->sp = ptregs->sp;
+		frame->fp = ptregs->regs[29];
+	}
 
 	if (arm64_in_kdump_text(bt, frame))
 		bt->flags |= BT_KDUMP_ADJUST;
-- 
1.8.3.1




More information about the Crash-utility mailing list