[Pdbg] [PATCH v2 26/39] gdbserver: initial thread support
Joel Stanley
joel at jms.id.au
Tue May 3 17:22:36 AEST 2022
On Wed, 20 Apr 2022 at 06:51, Nicholas Piggin <npiggin at gmail.com> wrote:
>
> Add a command-specific pointer to the struct thread that gdbserver
> can use, so it doesn't have to build its own structure of threads.
>
> Initially keep the PIR value in here, as a demonstration.
>
> Later PIR will be used to identify threads to the gdb client, and
> more data will be added to the gdb_thread structure to support
> debugging multiple threads.
>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
Reviewed-by: Joel Stanley <joel at jms.id.au>
> ---
> libpdbg/hwunit.h | 1 +
> src/pdbgproxy.c | 66 ++++++++++++++++++++++++++++++++++++------------
> 2 files changed, 51 insertions(+), 16 deletions(-)
>
> diff --git a/libpdbg/hwunit.h b/libpdbg/hwunit.h
> index 2ce41db8..563b5812 100644
> --- a/libpdbg/hwunit.h
> +++ b/libpdbg/hwunit.h
> @@ -139,6 +139,7 @@ struct core {
> struct thread {
> struct pdbg_target target;
> struct thread_state status;
> + void *gdbserver_priv;
> int id;
> struct thread_state (*state)(struct thread *);
> int (*step)(struct thread *, int);
> diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c
> index 393b37bf..b8ee2a06 100644
> --- a/src/pdbgproxy.c
> +++ b/src/pdbgproxy.c
> @@ -51,6 +51,11 @@ static int fd = -1;
> enum client_state {IDLE, SIGNAL_WAIT};
> static enum client_state state = IDLE;
>
> +/* Attached to thread->gdbserver_priv */
> +struct gdb_thread {
> + uint64_t pir;
> +};
> +
> static void destroy_client(int dead_fd);
>
> static uint8_t gdbcrc(char *data)
> @@ -666,7 +671,7 @@ static void SIGINT_handler(int sig)
> gdbserver_running = false;
> }
>
> -static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu, uint16_t port)
> +static int gdbserver_start(struct pdbg_target *adu, uint16_t port)
> {
> int sock, i;
> struct sigaction sa;
> @@ -682,7 +687,6 @@ static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu,
> }
>
> parser_init(callbacks);
> - thread_target = thread;
> adu_target = adu;
>
> sock = socket(PF_INET, SOCK_STREAM, 0);
> @@ -767,33 +771,40 @@ static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu,
>
> static int gdbserver(uint16_t port)
> {
> - struct pdbg_target *target, *adu, *thread = NULL;
> + struct pdbg_target *target, *adu, *first_target = NULL;
>
> for_each_path_target_class("thread", target) {
> - if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED)
> + struct thread *thread = target_to_thread(target);
> + struct gdb_thread *gdb_thread;
> +
> + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
> continue;
>
> - if (!thread) {
> - thread = target;
> + if (!pdbg_target_compatible(target, "ibm,power8-thread") &&
> + !pdbg_target_compatible(target, "ibm,power9-thread") &&
> + !pdbg_target_compatible(target, "ibm,power10-thread")) {
> + PR_ERROR("GDBSERVER is only available on POWER8,9,10\n");
> + return -1;
> + }
> +
> + gdb_thread = malloc(sizeof(struct gdb_thread));
> + memset(gdb_thread, 0, sizeof(*gdb_thread));
> + thread->gdbserver_priv = gdb_thread;
> +
> + if (!first_target) {
> + first_target = target;
> } else {
> fprintf(stderr, "GDB server cannot be run on multiple threads at once.\n");
> return 0;
> }
> }
>
> - if (!thread) {
> + if (!first_target) {
> fprintf(stderr, "No thread selected\n");
> return 0;
> }
>
> - if (!pdbg_target_compatible(thread, "ibm,power8-thread") &&
> - !pdbg_target_compatible(thread, "ibm,power9-thread") &&
> - !pdbg_target_compatible(thread, "ibm,power10-thread")) {
> - PR_ERROR("GDBSERVER is only available on POWER8,9,10\n");
> - return -1;
> - }
> -
> - if (pdbg_target_compatible(thread, "ibm,power9-thread")) {
> + if (pdbg_target_compatible(first_target, "ibm,power9-thread")) {
> /*
> * XXX: If we advertise no swbreak support on POWER9 does
> * that prevent the client using them?
> @@ -801,6 +812,29 @@ static int gdbserver(uint16_t port)
> PR_WARNING("Breakpoints may cause host crashes on POWER9 and should not be used\n");
> }
>
> + thread_target = first_target;
> +
> + for_each_path_target_class("thread", target) {
> + struct thread *thread = target_to_thread(target);
> + struct gdb_thread *gdb_thread;
> +
> + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
> + continue;
> +
> + gdb_thread = thread->gdbserver_priv;
> +
> + if (thread_getspr(target, SPR_PIR, &gdb_thread->pir)) {
> + PR_ERROR("Error reading PIR. Are all thread in the target cores quiesced?\n");
> + return 0;
> + }
> +
> + if (gdb_thread->pir & ~0xffffULL) {
> + /* This limit is just due to some string array sizes */
> + PR_ERROR("PIR exceeds 16-bits.");
> + return 0;
> + }
> + }
> +
> /* Select ADU target */
> pdbg_for_each_class_target("mem", adu) {
> if (pdbg_target_probe(adu) == PDBG_TARGET_ENABLED)
> @@ -812,7 +846,7 @@ static int gdbserver(uint16_t port)
> return 0;
> }
>
> - gdbserver_start(thread, adu, port);
> + gdbserver_start(adu, port);
>
> return 0;
> }
> --
> 2.35.1
>
> --
> Pdbg mailing list
> Pdbg at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/pdbg
More information about the Pdbg
mailing list