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@lists.crash-utility.osci.io/msg01085.html
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 | 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