175 lines
5.4 KiB
Diff
175 lines
5.4 KiB
Diff
From d3ef6e456629fc5711708a88872304da5159c1c6 Mon Sep 17 00:00:00 2001
|
|
From: Tao Liu <ltao@redhat.com>
|
|
Date: Wed, 25 Jun 2025 16:02:00 +1200
|
|
Subject: [PATCH 4/9] Call cmd_bt silently after "set pid"
|
|
|
|
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@broadcom.com>
|
|
Co-developed-by: Tao Liu <ltao@redhat.com>
|
|
Signed-off-by: Tao Liu <ltao@redhat.com>
|
|
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
|
---
|
|
arm64.c | 4 ++++
|
|
crash_target.c | 7 +++++++
|
|
kernel.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
|
|
ppc64.c | 4 ++++
|
|
task.c | 4 ++--
|
|
x86_64.c | 3 +++
|
|
6 files changed, 64 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/arm64.c b/arm64.c
|
|
index 1cdde5f12bd0..829130158902 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 71998ef2d806..ad1480c9188f 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 b8d3b7999974..e4213d7a663e 100644
|
|
--- a/kernel.c
|
|
+++ b/kernel.c
|
|
@@ -12002,3 +12002,47 @@ 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);
|
|
+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 7ac12feaee7d..532eb3fe4a7e 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 e07b479a3bec..ec04b556c337 100644
|
|
--- a/task.c
|
|
+++ b/task.c
|
|
@@ -3062,7 +3062,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();
|
|
}
|
|
@@ -3109,7 +3109,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 a46fb9d8b72b..ee23d8b5e41e 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.1
|
|
|