This patch is a preparation of gdb stack unwinding support. "set" command is extended with gdb context change: crash> set <pid> or crash> set <task> Then the task context of crash and gdb will both be switched to pid/task, and the following command: "bt" "gdb bt" will output the same task context. Co-developed-by: Aditya Gupta <adityag@xxxxxxxxxxxxx> Co-developed-by: Alexey Makhalov <alexey.makhalov@xxxxxxxxxxxx> Co-developed-by: Tao Liu <ltao@xxxxxxxxxx> Cc: Sourabh Jain <sourabhjain@xxxxxxxxxxxxx> Cc: Hari Bathini <hbathini@xxxxxxxxxxxxx> Cc: Mahesh J Salgaonkar <mahesh@xxxxxxxxxxxxx> Cc: Naveen N. Rao <naveen.n.rao@xxxxxxxxxxxxxxxxxx> Cc: Lianbo Jiang <lijiang@xxxxxxxxxx> Cc: HAGIO KAZUHITO(萩尾 一仁) <k-hagio-ab@xxxxxxx> Cc: Tao Liu <ltao@xxxxxxxxxx> Cc: Alexey Makhalov <alexey.makhalov@xxxxxxxxxxxx> Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> --- crash_target.c | 46 ++++++++++++++++++++++++++++++---------------- defs.h | 5 ++++- kernel.c | 11 ++++++++--- task.c | 21 +++++++++++++-------- tools.c | 8 ++++---- 5 files changed, 59 insertions(+), 32 deletions(-) diff --git a/crash_target.c b/crash_target.c index 1f62bf6..41f0f3a 100644 --- a/crash_target.c +++ b/crash_target.c @@ -28,7 +28,7 @@ void crash_target_init (void); extern "C" int gdb_readmem_callback(unsigned long, void *, int, int); extern "C" int crash_get_cpu_reg (int cpu, int regno, const char *regname, int regsize, void *val); - +extern "C" int gdb_change_thread_context (void); /* The crash target. */ @@ -63,26 +63,32 @@ public: }; -/* We just get all the registers, so we don't use regno. */ -void -crash_target::fetch_registers (struct regcache *regcache, int regno) +static void supply_registers(struct regcache *regcache, int regno) { gdb_byte regval[16]; int cpu = inferior_ptid.tid(); struct gdbarch *arch = regcache->arch (); + const char *regname = gdbarch_register_name(arch, regno); + int regsize = register_size(arch, regno); - for (int r = 0; r < gdbarch_num_regs (arch); r++) - { - const char *regname = gdbarch_register_name(arch, r); - int regsize = register_size (arch, r); - if (regsize > sizeof (regval)) - error (_("fatal error: buffer size is not enough to fit register value")); - - if (crash_get_cpu_reg (cpu, r, regname, regsize, (void *)®val)) - regcache->raw_supply (r, regval); - else - regcache->raw_supply (r, NULL); - } + if (regsize > sizeof (regval)) + error (_("fatal error: buffer size is not enough to fit register value")); + + if (crash_get_cpu_reg (cpu, regno, regname, regsize, (void *)®val)) + regcache->raw_supply (regno, regval); + else + regcache->raw_supply (regno, NULL); +} + +void +crash_target::fetch_registers (struct regcache *regcache, int regno) +{ + if (regno >= 0) { + supply_registers(regcache, regno); + } else if (regno == -1) { + for (int r = 0; r < gdbarch_num_regs (regcache->arch ()); r++) + supply_registers(regcache, r); + } } @@ -129,3 +135,11 @@ crash_target_init (void) /* Now, set up the frame cache. */ reinit_frame_cache (); } + +extern "C" int +gdb_change_thread_context (void) +{ + target_fetch_registers(get_current_regcache(), -1); + reinit_frame_cache(); + return TRUE; +} diff --git a/defs.h b/defs.h index 49e6923..9ffe7c9 100644 --- a/defs.h +++ b/defs.h @@ -6019,7 +6019,7 @@ extern char *help_map[]; * task.c */ void task_init(void); -int set_context(ulong, ulong); +int set_context(ulong, ulong, uint); void show_context(struct task_context *); ulong pid_to_task(ulong); ulong task_to_pid(ulong); @@ -8055,4 +8055,7 @@ enum x86_64_regnum { LAST_REGNUM }; +/* crash_target.c */ +extern int gdb_change_thread_context (void); + #endif /* !GDB_COMMON */ diff --git a/kernel.c b/kernel.c index 8a9d498..5d25b88 100644 --- a/kernel.c +++ b/kernel.c @@ -6507,15 +6507,20 @@ set_cpu(int cpu) if (hide_offline_cpu(cpu)) error(FATAL, "invalid cpu number: cpu %d is OFFLINE\n", cpu); - if ((task = get_active_task(cpu))) - set_context(task, NO_PID); + task = get_active_task(cpu); + + /* Check if context is already set to given cpu */ + if (task == CURRENT_TASK()) + return; + + if (task) + set_context(task, NO_PID, TRUE); else error(FATAL, "cannot determine active task on cpu %ld\n", cpu); show_context(CURRENT_CONTEXT()); } - /* * Collect the irq_desc[] entry along with its associated handler and * action structures. diff --git a/task.c b/task.c index d52ce0b..697a692 100644 --- a/task.c +++ b/task.c @@ -679,7 +679,7 @@ task_init(void) if (ACTIVE()) { active_pid = REMOTE() ? pc->server_pid : LOCAL_ACTIVE() ? pc->program_pid : 1; - set_context(NO_TASK, active_pid); + set_context(NO_TASK, active_pid, FALSE); tt->this_task = pid_to_task(active_pid); } else { @@ -691,7 +691,7 @@ task_init(void) else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE()) map_cpus_to_prstatus_kdump_cmprs(); please_wait("determining panic task"); - set_context(get_panic_context(), NO_PID); + set_context(get_panic_context(), NO_PID, TRUE); please_wait_done(); } @@ -2992,9 +2992,9 @@ refresh_context(ulong curtask, ulong curpid) struct task_context *tc; if (task_exists(curtask) && pid_exists(curpid)) { - set_context(curtask, NO_PID); + set_context(curtask, NO_PID, FALSE); } else { - set_context(tt->this_task, NO_PID); + set_context(tt->this_task, NO_PID, FALSE); complain = TRUE; if (STREQ(args[0], "set") && (argcnt == 2) && @@ -3060,7 +3060,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); + set_context(curtask, NO_PID, TRUE); sort_context_by_task(); } @@ -3107,7 +3107,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); + set_context(curtask, NO_PID, TRUE); sort_context_by_task(); } @@ -5288,7 +5288,7 @@ comm_exists(char *s) * that pid is selected. */ int -set_context(ulong task, ulong pid) +set_context(ulong task, ulong pid, uint update_gdb_thread) { int i; struct task_context *tc; @@ -5308,7 +5308,12 @@ set_context(ulong task, ulong pid) if (found) { CURRENT_CONTEXT() = tc; - return TRUE; + + /* change the selected thread in gdb, according to current context */ + if (update_gdb_thread) + return gdb_change_thread_context(); + else + return TRUE; } else { if (task) error(INFO, "cannot set context for task: %lx\n", task); diff --git a/tools.c b/tools.c index 1022d57..a8f9785 100644 --- a/tools.c +++ b/tools.c @@ -1871,7 +1871,7 @@ cmd_set(void) return; if (ACTIVE()) { - set_context(tt->this_task, NO_PID); + set_context(tt->this_task, NO_PID, TRUE); show_context(CURRENT_CONTEXT()); return; } @@ -1880,7 +1880,7 @@ cmd_set(void) error(INFO, "no panic task found!\n"); return; } - set_context(tt->panic_task, NO_PID); + set_context(tt->panic_task, NO_PID, TRUE); show_context(CURRENT_CONTEXT()); return; @@ -2559,14 +2559,14 @@ cmd_set(void) case STR_PID: pid = value; task = NO_TASK; - if (set_context(task, pid)) + if (set_context(task, pid, TRUE)) show_context(CURRENT_CONTEXT()); break; case STR_TASK: task = value; pid = NO_PID; - if (set_context(task, pid)) + if (set_context(task, pid, TRUE)) show_context(CURRENT_CONTEXT()); break; -- 2.40.1 -- 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