mirror of https://github.com/crash-utility/crash
arm64: Add gdb stack unwind support
Signed-off-by: Tao Liu <ltao@redhat.com>
This commit is contained in:
parent
89ff1e4573
commit
968debd0d5
120
arm64.c
120
arm64.c
|
@ -121,6 +121,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 */
|
||||
|
@ -197,6 +202,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.
|
||||
|
@ -549,6 +642,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();
|
||||
|
@ -683,6 +777,7 @@ arm64_init(int when)
|
|||
*/
|
||||
if (!LIVE())
|
||||
arm64_get_crash_notes();
|
||||
gdb_change_thread_context();
|
||||
break;
|
||||
|
||||
case LOG_ONLY:
|
||||
|
@ -4134,6 +4229,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) ||
|
||||
|
@ -4162,22 +4258,30 @@ 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);
|
||||
|
||||
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)
|
||||
|
|
36
defs.h
36
defs.h
|
@ -8143,6 +8143,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.
|
||||
|
|
Loading…
Reference in New Issue