Whenever extra stack is found, a user_regs structure is allocated and regs value copied there. Later the values will be retrived by get_current_task_reg() by given the thread's tid, aka the index of stack. Co-developed-by: Alexey Makhalov <alexey.makhalov@xxxxxxxxxxxx> Co-developed-by: Tao Liu <ltao@xxxxxxxxxx> Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> --- x86_64.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/x86_64.c b/x86_64.c index e544be8..ca745a6 100644 --- a/x86_64.c +++ b/x86_64.c @@ -3551,6 +3551,7 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in) irq_eframe = 0; last_process_stack_eframe = 0; bt->call_target = NULL; + extra_stacks_idx = 0; rsp = bt->stkptr; ms = machdep->machspec; @@ -4159,6 +4160,7 @@ x86_64_dwarf_back_trace_cmd(struct bt_info *bt_in) last_process_stack_eframe = 0; bt->call_target = NULL; bt->bptr = 0; + extra_stacks_idx = 0; rsp = bt->stkptr; if (!rsp) { error(INFO, "cannot determine starting stack pointer\n"); @@ -4546,6 +4548,9 @@ x86_64_back_trace(struct gnu_request *req, struct bt_info *bt) * */ +#define SET_REG_BITMAP(REGMAP, TYPE, MEMBER) \ + SET_BIT(REGMAP, REG_SEQ(TYPE, MEMBER)) + long x86_64_exception_frame(ulong flags, ulong kvaddr, char *local, struct bt_info *bt, FILE *ofp) @@ -4799,6 +4804,22 @@ x86_64_exception_frame(ulong flags, ulong kvaddr, char *local, } else if (machdep->flags & ORC) bt->bptr = rbp; + /* + * Preserve registers set for each additional in-kernel stack + */ + if (!(cs & 3) && verified && flags & EFRAME_PRINT && + extra_stacks_idx < MAX_EXCEPTION_STACKS) { + 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, + pt_regs_buf, SIZE(pt_regs)); + for (int i = 0; i < SIZE(pt_regs)/sizeof(long); i++) + SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, i); + gdb_add_substack(extra_stacks_idx++); + } + if (kvaddr) FREEBUF(pt_regs_buf); @@ -5002,9 +5023,6 @@ get_reg_from_inactive_task_frame(struct bt_info *bt, char *reg_name, return reg_value; } -#define SET_REG_BITMAP(REGMAP, TYPE, MEMBER) \ - SET_BIT(REGMAP, REG_SEQ(TYPE, MEMBER)) - /* * Get a stack frame combination of pc and ra from the most relevent spot. */ @@ -5092,11 +5110,22 @@ x86_64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp) * ip and sp in the end of the function. */ if (bt->flags & BT_DUMPFILE_SEARCH) { - FREEBUF(ur_bitmap); - bt->need_free = FALSE; *pcp = pcp_save; *spp = spp_save; - return x86_64_get_dumpfile_stack_frame(bt, pcp, spp); + /* + * pcp/spp_save is read from elf notes, for panic + * task, we'll continue to use the original elf + * notes to get regs; for other active tasks, + * we'll update the sp/ip into our own ur_bitmap. + */ + x86_64_get_dumpfile_stack_frame(bt, pcp, spp); + if (tt->panic_task == bt->task) { + FREEBUF(ur_bitmap); + bt->need_free = FALSE; + return; + } else { + sp = *spp; + } } } } else { @@ -5106,11 +5135,16 @@ x86_64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp) SET_REG_BITMAP(ur_bitmap->bitmap, x86_64_user_regs_struct, bp); } else { if (bt->flags & BT_DUMPFILE_SEARCH) { - FREEBUF(ur_bitmap); - bt->need_free = FALSE; *pcp = pcp_save; *spp = spp_save; - return x86_64_get_dumpfile_stack_frame(bt, pcp, spp); + x86_64_get_dumpfile_stack_frame(bt, pcp, spp); + if (tt->panic_task == bt->task) { + FREEBUF(ur_bitmap); + bt->need_free = FALSE; + return; + } else { + sp = *spp; + } } } } @@ -9256,6 +9290,12 @@ x86_64_get_current_task_reg(int regno, const char *name, if (!tc) return FALSE; + /* Non zero stack ID, use extra stacks regs */ + if (sid && sid <= extra_stacks_idx) { + ur_bitmap = extra_stacks_regs[sid - 1]; + goto get_sub; + } + /* * Task is active, grab CPU's registers */ @@ -9280,6 +9320,7 @@ x86_64_get_current_task_reg(int regno, const char *name, } /* Get subset registers from stack frame*/ +get_sub: switch (regno) { CHECK_REG_CASE(RAX, ax); CHECK_REG_CASE(RBX, bx); @@ -9341,7 +9382,7 @@ get_all: COPY_REG_CASE(ORIG_RAX, orig_ax); } - if (bt_info.need_free) { + if (!sid && bt_info.need_free) { FREEBUF(ur_bitmap); bt_info.need_free = FALSE; } -- 2.47.0 -- 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