[Crash-utility] [PATCH v7 15/15] arm64: Add gdb stack unwinding support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Cc: Sourabh Jain <sourabhjain@xxxxxxxxxxxxx>
Cc: Hari Bathini <hbathini@xxxxxxxxxxxxx>
Cc: Mahesh J Salgaonkar <mahesh@xxxxxxxxxxxxx>
Cc: Naveen N. Rao <naveen.n.rao@xxxxxxxxxxxxxxxxxx>
Cc: Lianbo Jiang <lijiang@xxxxxxxxxx>
Cc: HAGIO KAZUHITO(萩尾 一仁) <k-hagio-ab@xxxxxxx>
Cc: Tao Liu <ltao@xxxxxxxxxx>
Cc: Alexey Makhalov <alexey.makhalov@xxxxxxxxxxxx>
Cc: Aditya Gupta <adityag@xxxxxxxxxxxxx>
Signed-off-by: Tao Liu <ltao@xxxxxxxxxx>
---
 arm64.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 defs.h  |  36 +++++++++++++++++
 2 files changed, 148 insertions(+), 8 deletions(-)

diff --git a/arm64.c b/arm64.c
index 06e7451..cedaee9 100644
--- a/arm64.c
+++ b/arm64.c
@@ -120,6 +120,11 @@ static void arm64_get_struct_page_size(struct machine_specific *ms);
 #define mte_tag_reset(addr)	(((ulong)addr & ~mte_tag_shifted(KASAN_TAG_KERNEL)) | \
 					mte_tag_shifted(KASAN_TAG_KERNEL))
 
+struct user_regs_bitmap_struct {
+	struct arm64_pt_regs ur;
+	ulong bitmap[32];
+};
+
 static inline bool is_mte_kvaddr(ulong addr)
 {
 	/* check for ARM64_MTE enabled */
@@ -196,6 +201,94 @@ out:
 		machdep->is_page_ptr = arm64_vmemmap_is_page_ptr;
 }
 
+static int
+arm64_get_current_task_reg(int regno, const char *name,
+                   int size, void *value)
+{
+	struct bt_info bt_info, bt_setup;
+	struct task_context *tc;
+	struct user_regs_bitmap_struct *ur_bitmap;
+	ulong ip, sp;
+	bool ret = FALSE;
+
+	switch (regno) {
+		case X0_REGNUM ... PC_REGNUM:
+		break;
+	default:
+		return FALSE;
+	}
+
+	tc = CURRENT_CONTEXT();
+	if (!tc)
+		return FALSE;
+	BZERO(&bt_setup, sizeof(struct bt_info));
+	clone_bt_info(&bt_setup, &bt_info, tc);
+	fill_stackbuf(&bt_info);
+
+	get_dumpfile_regs(&bt_info, &sp, &ip);
+	if (bt_info.stackbuf)
+		FREEBUF(bt_info.stackbuf);
+	ur_bitmap = (struct user_regs_bitmap_struct *)bt_info.machdep;
+	if (!ur_bitmap)
+		return FALSE;
+
+	if (!bt_info.need_free) {
+		goto get_all;
+	}
+
+	switch (regno) {
+	case X0_REGNUM ... X30_REGNUM:
+		if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
+		    REG_SEQ(arm64_pt_regs, regs[0]) + regno - X0_REGNUM)) {
+			FREEBUF(ur_bitmap);
+			return FALSE;
+		}
+		break;
+	case SP_REGNUM:
+		if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
+		    REG_SEQ(arm64_pt_regs, sp))) {
+			FREEBUF(ur_bitmap);
+			return FALSE;
+		}
+		break;
+	case PC_REGNUM:
+		if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
+		    REG_SEQ(arm64_pt_regs, pc))) {
+			FREEBUF(ur_bitmap);
+			return FALSE;
+		}
+		break;
+	}
+
+get_all:
+	switch (regno) {
+	case X0_REGNUM ... X30_REGNUM:
+		if (size != sizeof(ur_bitmap->ur.regs[regno]))
+			break;
+		memcpy(value, &ur_bitmap->ur.regs[regno], size);
+		ret = TRUE;
+		break;
+	case SP_REGNUM:
+		if (size != sizeof(ur_bitmap->ur.sp))
+			break;
+		memcpy(value, &ur_bitmap->ur.sp, size);
+		ret = TRUE;
+		break;
+	case PC_REGNUM:
+		if (size != sizeof(ur_bitmap->ur.pc))
+			break;
+		memcpy(value, &ur_bitmap->ur.pc, size);
+		ret = TRUE;
+		break;
+	}
+
+	if (bt_info.need_free) {
+		FREEBUF(ur_bitmap);
+		bt_info.need_free = FALSE;
+	}
+	return ret;
+}
+
 /*
  * Do all necessary machine-specific setup here. This is called several times
  * during initialization.
@@ -520,6 +613,7 @@ arm64_init(int when)
 		machdep->dumpfile_init = NULL;
 		machdep->verify_line_number = NULL;
 		machdep->init_kernel_pgd = arm64_init_kernel_pgd;
+		machdep->get_current_task_reg = arm64_get_current_task_reg;
 
 		/* use machdep parameters */
 		arm64_calc_phys_offset();
@@ -654,6 +748,7 @@ arm64_init(int when)
 		 */
 		if (!LIVE()) 
 			arm64_get_crash_notes();
+		gdb_change_thread_context();
 		break;
 
 	case LOG_ONLY:
@@ -4011,6 +4106,7 @@ arm64_get_dumpfile_stackframe(struct bt_info *bt, struct arm64_stackframe *frame
 try_kernel:
 		frame->sp = ptregs->sp;
 		frame->fp = ptregs->regs[29];
+		bt->machdep = ptregs;
 	}
 
 	if (arm64_in_kdump_text(bt, frame) || 
@@ -4039,23 +4135,31 @@ arm64_get_stackframe(struct bt_info *bt, struct arm64_stackframe *frame)
 static void
 arm64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
 {
-	int ret;
+	struct user_regs_bitmap_struct *ur_bitmap;
 	struct arm64_stackframe stackframe = { 0 };
 
 	if (DUMPFILE() && is_task_active(bt->task)) {
-		ret = arm64_get_dumpfile_stackframe(bt, &stackframe);
+		arm64_get_dumpfile_stackframe(bt, &stackframe);
+		bt->need_free = FALSE;
 	} else {
 		if (bt->flags & BT_SKIP_IDLE)
 			bt->flags &= ~BT_SKIP_IDLE;
 
-		ret = arm64_get_stackframe(bt, &stackframe);
+		arm64_get_stackframe(bt, &stackframe);
+
+		ur_bitmap = (struct user_regs_bitmap_struct *)GETBUF(sizeof(*ur_bitmap));
+		memset(ur_bitmap, 0, sizeof(*ur_bitmap));
+		ur_bitmap->ur.pc = stackframe.pc;
+		ur_bitmap->ur.sp = stackframe.sp;
+		ur_bitmap->ur.regs[29] = stackframe.fp;
+		SET_BIT(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, pc));
+		SET_BIT(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, sp));
+		SET_BIT(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, regs[0])
+						+ X29_REGNUM - X0_REGNUM);
+		bt->machdep = ur_bitmap;
+		bt->need_free = TRUE;
 	}
 
-	if (!ret)
-		error(WARNING, 
-			"cannot determine starting stack frame for task %lx\n",
-				bt->task);
-
 	bt->frameptr = stackframe.fp;
 	if (pcp)
 		*pcp = stackframe.pc;
diff --git a/defs.h b/defs.h
index abfa923..104ec48 100644
--- a/defs.h
+++ b/defs.h
@@ -8111,6 +8111,42 @@ enum x86_64_regnum {
         LAST_REGNUM
 };
 
+enum arm64_regnum {
+	X0_REGNUM,
+	X1_REGNUM,
+	X2_REGNUM,
+	X3_REGNUM,
+	X4_REGNUM,
+	X5_REGNUM,
+	X6_REGNUM,
+	X7_REGNUM,
+	X8_REGNUM,
+	X9_REGNUM,
+	X10_REGNUM,
+	X11_REGNUM,
+	X12_REGNUM,
+	X13_REGNUM,
+	X14_REGNUM,
+	X15_REGNUM,
+	X16_REGNUM,
+	X17_REGNUM,
+	X18_REGNUM,
+	X19_REGNUM,
+	X20_REGNUM,
+	X21_REGNUM,
+	X22_REGNUM,
+	X23_REGNUM,
+	X24_REGNUM,
+	X25_REGNUM,
+	X26_REGNUM,
+	X27_REGNUM,
+	X28_REGNUM,
+	X29_REGNUM,
+	X30_REGNUM,
+	SP_REGNUM,
+	PC_REGNUM,
+};
+
 /*
  * Register numbers to make crash_target->fetch_registers()
  * ---> machdep->get_current_task_reg() work properly.
-- 
2.40.1
--
Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines: https://github.com/crash-utility/crash/wiki




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux