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> Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> --- arm64.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- defs.h | 36 ++++++++++++++++++ 2 files changed, 146 insertions(+), 5 deletions(-) diff --git a/arm64.c b/arm64.c index 06e7451..64bebb1 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) || @@ -4040,21 +4136,30 @@ 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); + bt->need_free = FALSE; } else { if (bt->flags & BT_SKIP_IDLE) bt->flags &= ~BT_SKIP_IDLE; ret = arm64_get_stackframe(bt, &stackframe); - } - if (!ret) - error(WARNING, - "cannot determine starting stack frame for task %lx\n", - bt->task); + 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; + } bt->frameptr = stackframe.fp; if (pcp) 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