diff --git a/crash_target.c b/crash_target.c index 45548067..a9d7eea8 100644 --- a/crash_target.c +++ b/crash_target.c @@ -29,6 +29,8 @@ extern "C" int gdb_readmem_callback(unsigned long, void *, int, int); extern "C" int crash_get_nr_cpus(void); extern "C" int crash_get_cpu_reg (int cpu, int regno, const char *regname, int regsize, void *val); +extern "C" int gdb_change_cpu_context (unsigned int cpu); +extern "C" int set_cpu (int cpu); /* The crash target. */ @@ -133,3 +135,25 @@ crash_target_init (void) /* Now, set up the frame cache. */ reinit_frame_cache (); } + +/* + * Change gdb's thread context to the thread on given CPU + **/ +extern "C" int +gdb_change_cpu_context(unsigned int cpu) +{ + ptid_t ptid = ptid_t(CRASH_INFERIOR_PID, 0, cpu); + inferior *inf = current_inferior (); + thread_info *tp = find_thread_ptid (inf, ptid); + + if (tp == nullptr) + return FALSE; + + /* Making sure that crash's context is same */ + set_cpu(cpu); + + /* Switch to the thread */ + switch_to_thread(tp); + return TRUE; +} + diff --git a/defs.h b/defs.h index 694d2809..50fe25c0 100644 --- a/defs.h +++ b/defs.h @@ -8173,4 +8173,7 @@ enum ppc64_regnum { PPC64_VRSAVE_REGNU = 139 }; +/* crash_target.c */ +extern int gdb_change_cpu_context (unsigned int cpu); + #endif /* !GDB_COMMON */ diff --git a/gdb-10.2.patch b/gdb-10.2.patch index a7018a24..677bd9b3 100644 --- a/gdb-10.2.patch +++ b/gdb-10.2.patch @@ -10,6 +10,7 @@ tar xvzmf gdb-10.2.tar.gz \ gdb-10.2/gdb/symtab.c \ + gdb-10.2/gdb/thread.c \ gdb-10.2/gdb/printcmd.c \ gdb-10.2/gdb/symfile.c \ gdb-10.2/gdb/Makefile.in \ @@ -16057,3 +16058,32 @@ exit 0 m10200-dis.c m10200-opc.c m10300-dis.c +--- gdb-10.2/gdb/thread.c.orig ++++ gdb-10.2/gdb/thread.c +@@ -58,6 +58,11 @@ static int highest_thread_num; + /* The current/selected thread. */ + static thread_info *current_thread_; + ++#ifdef CRASH_MERGE ++/* Function to set cpu, defined by crash-utility */ ++extern "C" void set_cpu (int); ++#endif ++ + /* RAII type used to increase / decrease the refcount of each thread + in a given list of threads. */ + +@@ -1896,7 +1901,13 @@ thread_command (const char *tidstr, int from_tty) + { + ptid_t previous_ptid = inferior_ptid; + +- thread_select (tidstr, parse_thread_id (tidstr, NULL)); ++ struct thread_info* thread_id = parse_thread_id (tidstr, NULL); ++ ++#ifdef CRASH_MERGE ++ set_cpu(thread_id->ptid.tid()); ++#endif ++ ++ thread_select (tidstr, thread_id); + + /* Print if the thread has not changed, otherwise an event will + be sent. */ diff --git a/kernel.c b/kernel.c index 661ef0e2..93af36fc 100644 --- a/kernel.c +++ b/kernel.c @@ -6527,7 +6527,13 @@ 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))) + 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); else error(FATAL, "cannot determine active task on cpu %ld\n", cpu); diff --git a/task.c b/task.c index ebdb5be3..3a190caf 100644 --- a/task.c +++ b/task.c @@ -5301,7 +5301,9 @@ set_context(ulong task, ulong pid) if (found) { CURRENT_CONTEXT() = tc; - return TRUE; + + /* change the selected thread in gdb, according to current context */ + return gdb_change_cpu_context(tc->processor); } else { if (task) error(INFO, "cannot set context for task: %lx\n", task);