[Crash-utility] [PATCH v2 2/5] Call cmd_bt silently after "set pid"

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

 



Cmd bt will list multi-stacks of one task. After we "set <pid>" switch
context to one task, we first need a bt call to detect the multi-stacks,
however we don't want any console output from it, so a nullfp is used for
output receive. The silent bt call is only triggered once as part of task
context switch by cmd set.

A array of user_regs pointers is reserved for each supported arch. If one
extra stack found, a user_regs structure will be allocated for storing regs
value of the stack.

Co-developed-by: Alexey Makhalov <alexey.makhalov@xxxxxxxxxxxx>
Co-developed-by: Tao Liu <ltao@xxxxxxxxxx>
Signed-off-by: Tao Liu <ltao@xxxxxxxxxx>
---
 arm64.c        |  4 ++++
 crash_target.c |  7 +++++++
 kernel.c       | 43 +++++++++++++++++++++++++++++++++++++++++++
 ppc64.c        |  4 ++++
 task.c         |  4 ++--
 x86_64.c       |  3 +++
 6 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/arm64.c b/arm64.c
index 1cdde5f..8291301 100644
--- a/arm64.c
+++ b/arm64.c
@@ -126,6 +126,10 @@ struct user_regs_bitmap_struct {
 	ulong bitmap[32];
 };
 
+#define MAX_EXCEPTION_STACKS 7
+ulong extra_stacks_idx = 0;
+struct user_regs_bitmap_struct *extra_stacks_regs[MAX_EXCEPTION_STACKS] = {0};
+
 static inline bool is_mte_kvaddr(ulong addr)
 {
 	/* check for ARM64_MTE enabled */
diff --git a/crash_target.c b/crash_target.c
index 71998ef..ad1480c 100644
--- a/crash_target.c
+++ b/crash_target.c
@@ -31,6 +31,9 @@ extern "C" int crash_get_current_task_reg (int regno, const char *regname,
 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);
+#if defined (X86_64) || defined (ARM64) || defined (PPC64)
+extern "C" void silent_call_bt(void);
+#endif
 
 /* The crash target.  */
 
@@ -164,6 +167,10 @@ gdb_change_thread_context (void)
   /* 3rd, refresh regcache for tid 0 */
   target_fetch_registers(get_thread_regcache(inferior_thread()), -1);
   reinit_frame_cache();
+#if defined (X86_64) || defined (ARM64) || defined (PPC64)
+  /* 4th, invoke bt silently to refresh the additional stacks */
+  silent_call_bt();
+#endif
   return TRUE;
 }
 
diff --git a/kernel.c b/kernel.c
index 612b956..18b125c 100644
--- a/kernel.c
+++ b/kernel.c
@@ -12002,3 +12002,46 @@ int get_linux_banner_from_vmlinux(char *buf, size_t size)
 
 	return TRUE;
 }
+
+#if defined(X86_64) || defined(ARM64) || defined(PPC64)
+extern ulong extra_stacks_idx;
+extern void *extra_stacks_regs[];
+void silent_call_bt(void)
+{
+	jmp_buf main_loop_env_save;
+	unsigned long long flags_save = pc->flags;
+	FILE *fp_save = fp;
+	FILE *error_fp_save = pc->error_fp;
+	/* Redirect all cmd_bt() outputs into null */
+	fp = pc->nullfp;
+	pc->error_fp = pc->nullfp;
+
+	for (int i = 0; i < extra_stacks_idx; i++) {
+		/* Note: GETBUF/FREEBUF is not applicable for extra_stacks_regs,
+		   because we are reserving extra_stacks_regs by cmd_bt()
+		   for later use. But GETBUF/FREEBUF is designed for use only
+		   within one cmd. See process_command_line() -> restore_sanity()
+		   -> free_all_bufs(). So we use malloc/free instead. */
+		free(extra_stacks_regs[i]);
+		extra_stacks_regs[i] = NULL;
+	}
+	/* Prepare args used by cmd_bt() */
+	sprintf(pc->command_line, "bt\n");
+	argcnt = parse_line(pc->command_line, args);
+	optind = 1;
+	pc->flags |= RUNTIME;
+
+	/* Catch error FATAL generated by cmd_bt() if any */
+	memcpy(&main_loop_env_save, &pc->main_loop_env, sizeof(jmp_buf));
+	if (setjmp(pc->main_loop_env)) {
+		goto out;
+	}
+	cmd_bt();
+out:
+	/* Restore all */
+	memcpy(&pc->main_loop_env, &main_loop_env_save, sizeof(jmp_buf));
+	pc->flags = flags_save;
+	fp = fp_save;
+	pc->error_fp = error_fp_save;
+}
+#endif
diff --git a/ppc64.c b/ppc64.c
index 7ac12fe..532eb3f 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -80,6 +80,10 @@ struct user_regs_bitmap_struct {
 	ulong bitmap[32];
 };
 
+#define MAX_EXCEPTION_STACKS 7
+ulong extra_stacks_idx = 0;
+struct user_regs_bitmap_struct *extra_stacks_regs[MAX_EXCEPTION_STACKS] = {0};
+
 static int is_opal_context(ulong sp, ulong nip)
 {
 	uint64_t opal_start, opal_end;
diff --git a/task.c b/task.c
index 49f771e..869f584 100644
--- a/task.c
+++ b/task.c
@@ -3061,7 +3061,7 @@ sort_context_array(void)
 	curtask = CURRENT_TASK();
 	qsort((void *)tt->context_array, (size_t)tt->running_tasks,
         	sizeof(struct task_context), sort_by_pid);
-	set_context(curtask, NO_PID, TRUE);
+	set_context(curtask, NO_PID, FALSE);
 
 	sort_context_by_task();
 }
@@ -3108,7 +3108,7 @@ sort_context_array_by_last_run(void)
 	curtask = CURRENT_TASK();
 	qsort((void *)tt->context_array, (size_t)tt->running_tasks,
         	sizeof(struct task_context), sort_by_last_run);
-	set_context(curtask, NO_PID, TRUE);
+	set_context(curtask, NO_PID, FALSE);
 
 	sort_context_by_task();
 }
diff --git a/x86_64.c b/x86_64.c
index a46fb9d..ee23d8b 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -160,6 +160,9 @@ struct user_regs_bitmap_struct {
 	ulong bitmap[32];
 };
 
+ulong extra_stacks_idx = 0;
+struct user_regs_bitmap_struct *extra_stacks_regs[MAX_EXCEPTION_STACKS] = {0};
+
 /*
  *  Do all necessary machine-specific setup here.  This is called several
  *  times during initialization.
-- 
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