Previously, only one thread is created in crash target by [1]. And this one thread will work as the common container for different tasks whenever "set <pid>" to it. Its tid number is 0 and will never be deleted. In order to support multi-stacks, we enable multi-threads in crash target. Each thread will represent one stack, and "info threads" will list all available stacks, "thread <id>" will switch to it. Since multi-stacks is task binded, each task switching will trigger a thread delete of those tid number other than 0. In addition, we will pass the tid number to each arch's get_current_task_reg(), in order to retrive the regs value of the specific stack. [1]: https://www.mail-archive.com/devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx/msg01085.html Co-developed-by: Alexey Makhalov <alexey.makhalov@xxxxxxxxxxxx> Co-developed-by: Tao Liu <ltao@xxxxxxxxxx> Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> --- arm64.c | 2 +- crash_target.c | 42 +++++++++++++++++++++++++++++++++++++++--- defs.h | 3 ++- gdb_interface.c | 6 +++--- ppc64.c | 4 ++-- x86_64.c | 4 ++-- 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/arm64.c b/arm64.c index ef4a2b8..1cdde5f 100644 --- a/arm64.c +++ b/arm64.c @@ -204,7 +204,7 @@ out: static int arm64_get_current_task_reg(int regno, const char *name, - int size, void *value) + int size, void *value, int sid) { struct bt_info bt_info, bt_setup; struct task_context *tc; diff --git a/crash_target.c b/crash_target.c index 1080976..c5ad1df 100644 --- a/crash_target.c +++ b/crash_target.c @@ -27,8 +27,9 @@ void crash_target_init (void); extern "C" int gdb_readmem_callback(unsigned long, void *, int, int); extern "C" int crash_get_current_task_reg (int regno, const char *regname, - int regsize, void *val); + int regsize, void *val, int sid); extern "C" int gdb_change_thread_context (void); +extern "C" int gdb_add_substack (int); extern "C" void crash_get_current_task_info(unsigned long *pid, char **comm); /* The crash target. */ @@ -66,7 +67,12 @@ public: crash_get_current_task_info(&pid, &comm); return string_printf ("%ld %s", pid, comm); } - + const char *extra_thread_info (thread_info *tp) override + { + static char buf[16] = {0}; + snprintf(buf, sizeof(buf), "stack %ld", tp->ptid.tid()); + return buf; + } }; static void supply_registers(struct regcache *regcache, int regno) @@ -79,7 +85,7 @@ static void supply_registers(struct regcache *regcache, int regno) if (regsize > sizeof (regval)) error (_("fatal error: buffer size is not enough to fit register value")); - if (crash_get_current_task_reg (regno, regname, regsize, (void *)®val)) + if (crash_get_current_task_reg (regno, regname, regsize, (void *)®val, inferior_thread()->ptid.tid())) regcache->raw_supply (regno, regval); else regcache->raw_supply (regno, NULL); @@ -144,7 +150,37 @@ crash_target_init (void) extern "C" int gdb_change_thread_context (void) { + /* 1st, switch to tid 0 if we are not */ + if (inferior_thread()->ptid.tid()) { + switch_to_thread (current_inferior()->thread_list); + } + /* 2nd, delete threads whose tid is not 0 */ + for (thread_info *tp : current_inferior()->threads_safe()) { + if (tp->ptid.tid() && tp->deletable()) { + delete_thread_silent(tp); + current_inferior()->highest_thread_num--; + } + } + /* 3rd, refresh regcache for tid 0 */ target_fetch_registers(get_current_regcache(), -1); reinit_frame_cache(); return TRUE; } + +/* Add a thread for each additional stack. Use stack ID as a thread ID */ +extern "C" int +gdb_add_substack (int sid) +{ + thread_info *tp; + thread_info *current_thread = inferior_thread(); + + ptid_t ptid = ptid_t(CRASH_INFERIOR_PID, 0, sid + 1); + tp = find_thread_ptid (current_inferior(), ptid); + if (tp == nullptr) { + tp = add_thread_silent(current_inferior()->process_target(), ptid); + } + switch_to_thread (tp); + target_fetch_registers(get_thread_regcache(tp), -1); + switch_to_thread (current_thread); + return TRUE; +} \ No newline at end of file diff --git a/defs.h b/defs.h index d8d378e..3e4a1bb 100644 --- a/defs.h +++ b/defs.h @@ -1081,7 +1081,7 @@ struct machdep_table { void (*get_irq_affinity)(int); void (*show_interrupts)(int, ulong *); int (*is_page_ptr)(ulong, physaddr_t *); - int (*get_current_task_reg)(int, const char *, int, void *); + int (*get_current_task_reg)(int, const char *, int, void *, int); int (*is_cpu_prstatus_valid)(int cpu); }; @@ -8321,5 +8321,6 @@ enum ppc64_regnum { /* crash_target.c */ extern int gdb_change_thread_context (void); +extern int gdb_add_substack (int); #endif /* !GDB_COMMON */ diff --git a/gdb_interface.c b/gdb_interface.c index 315711e..c138c94 100644 --- a/gdb_interface.c +++ b/gdb_interface.c @@ -1074,12 +1074,12 @@ unsigned long crash_get_kaslr_offset(void) /* Callbacks for crash_target */ int crash_get_current_task_reg (int regno, const char *regname, - int regsize, void *value); + int regsize, void *value, int sid); int crash_get_current_task_reg (int regno, const char *regname, - int regsize, void *value) + int regsize, void *value, int sid) { if (!machdep->get_current_task_reg) return FALSE; - return machdep->get_current_task_reg(regno, regname, regsize, value); + return machdep->get_current_task_reg(regno, regname, regsize, value, sid); } diff --git a/ppc64.c b/ppc64.c index 782107b..7ac12fe 100644 --- a/ppc64.c +++ b/ppc64.c @@ -56,7 +56,7 @@ static char * ppc64_check_eframe(struct ppc64_pt_regs *); static void ppc64_print_eframe(char *, struct ppc64_pt_regs *, struct bt_info *); static int ppc64_get_current_task_reg(int regno, const char *name, int size, - void *value); + void *value, int); static void parse_cmdline_args(void); static int ppc64_paca_percpu_offset_init(int); static void ppc64_init_cpu_info(void); @@ -2512,7 +2512,7 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs, static int ppc64_get_current_task_reg(int regno, const char *name, int size, - void *value) + void *value, int sid) { struct bt_info bt_info, bt_setup; struct task_context *tc; diff --git a/x86_64.c b/x86_64.c index c254c6e..53ae3ef 100644 --- a/x86_64.c +++ b/x86_64.c @@ -126,7 +126,7 @@ static int x86_64_get_framesize(struct bt_info *, ulong, ulong, char *); static void x86_64_framesize_debug(struct bt_info *); static void x86_64_get_active_set(void); static int x86_64_get_kvaddr_ranges(struct vaddr_range *); -static int x86_64_get_current_task_reg(int, const char *, int, void *); +static int x86_64_get_current_task_reg(int, const char *, int, void *, int); static int x86_64_verify_paddr(uint64_t); static void GART_init(void); static void x86_64_exception_stacks_init(void); @@ -9233,7 +9233,7 @@ x86_64_get_kvaddr_ranges(struct vaddr_range *vrp) static int x86_64_get_current_task_reg(int regno, const char *name, - int size, void *value) + int size, void *value, int sid) { struct bt_info bt_info, bt_setup; struct task_context *tc; -- 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