[Crash-utility] [PATCH v1 1/5] Add multi-threads support in crash target

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 *)&regval))
+  if (crash_get_current_task_reg (regno, regname, regsize, (void *)&regval, 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




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux