Co-developed-by: Alexey Makhalov <alexey.makhalov(a)broadcom.com>
Co-developed-by: Tao Liu <ltao(a)redhat.com>
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
arm64.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 52 insertions(+), 4 deletions(-)
diff --git a/arm64.c b/arm64.c
index 8291301..e72b5f4 100644
--- a/arm64.c
+++ b/arm64.c
@@ -226,6 +226,12 @@ arm64_get_current_task_reg(int regno, const char *name,
tc = CURRENT_CONTEXT();
if (!tc)
return FALSE;
+
+ if (sid && sid <= extra_stacks_idx) {
+ ur_bitmap = extra_stacks_regs[extra_stacks_idx - 1];
+ goto get_sub;
+ }
+
BZERO(&bt_setup, sizeof(struct bt_info));
clone_bt_info(&bt_setup, &bt_info, tc);
fill_stackbuf(&bt_info);
@@ -241,25 +247,29 @@ arm64_get_current_task_reg(int regno, const char *name,
goto get_all;
}
+get_sub:
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);
+ if (!sid)
+ 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);
+ if (!sid)
+ 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);
+ if (!sid)
+ FREEBUF(ur_bitmap);
return FALSE;
}
break;
@@ -287,7 +297,7 @@ get_all:
break;
}
- if (bt_info.need_free) {
+ if (!sid && bt_info.need_free) {
FREEBUF(ur_bitmap);
bt_info.need_free = FALSE;
}
@@ -3680,6 +3690,7 @@ arm64_back_trace_cmd(struct bt_info *bt)
int level;
ulong exception_frame;
FILE *ofp;
+ extra_stacks_idx = 0;
if (bt->flags & BT_OPT_BACK_TRACE) {
if (machdep->flags & UNW_4_14) {
@@ -3710,6 +3721,18 @@ arm64_back_trace_cmd(struct bt_info *bt)
stackframe.pc = GET_STACK_ULONG(bt->bptr);
stackframe.sp = bt->bptr + 8;
bt->frameptr = stackframe.sp;
+
+ if (!extra_stacks_regs[extra_stacks_idx]) {
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
+ GETBUF(sizeof(struct user_regs_bitmap_struct *));
+ }
+ extra_stacks_regs[extra_stacks_idx]->ur.pc = stackframe.pc;
+ extra_stacks_regs[extra_stacks_idx]->ur.sp = stackframe.fp;
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
+ REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
+ REG_SEQ(arm64_pt_regs, sp));
+ gdb_add_substack (extra_stacks_idx++);
} else if (bt->hp && bt->hp->esp) {
if (arm64_on_irq_stack(bt->tc->processor, bt->hp->esp)) {
arm64_set_irq_stack(bt);
@@ -3795,6 +3818,19 @@ arm64_back_trace_cmd(struct bt_info *bt)
bt->flags &= ~BT_IRQSTACK;
if (arm64_switch_stack(bt, &stackframe, ofp) == USER_MODE)
break;
+ else if (tt->panic_task == bt->task) {
+ if (!extra_stacks_regs[extra_stacks_idx]) {
+ extra_stacks_regs[extra_stacks_idx] =
+ (struct user_regs_bitmap_struct *)
+ GETBUF(sizeof(struct user_regs_bitmap_struct *));
+ }
+ memcpy(&extra_stacks_regs[extra_stacks_idx]->ur,
+ &bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(exception_frame))],
+ sizeof(struct arm64_pt_regs));
+ for (int i = 0; i < sizeof(struct arm64_pt_regs)/sizeof(long); i++)
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, i);
+ gdb_add_substack (extra_stacks_idx++);
+ }
}
if ((bt->flags & BT_OVERFLOW_STACK) &&
@@ -3844,6 +3880,18 @@ arm64_back_trace_cmd_v2(struct bt_info *bt)
stackframe.pc = GET_STACK_ULONG(bt->bptr + 8);
stackframe.sp = bt->bptr + 16;
bt->frameptr = stackframe.fp;
+
+ if (!extra_stacks_regs[extra_stacks_idx]) {
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
+ GETBUF(sizeof(struct user_regs_bitmap_struct *));
+ }
+ extra_stacks_regs[extra_stacks_idx]->ur.pc = stackframe.pc;
+ extra_stacks_regs[extra_stacks_idx]->ur.sp = stackframe.fp;
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
+ REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
+ REG_SEQ(arm64_pt_regs, sp));
+ gdb_add_substack (extra_stacks_idx++);
} else {
if (arm64_on_irq_stack(bt->tc->processor, bt->frameptr)) {
arm64_set_irq_stack(bt);
--
2.47.0