From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 128743 invoked by alias); 25 Sep 2015 02:59:33 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 128680 invoked by uid 440); 25 Sep 2015 02:59:25 -0000 Date: Fri, 25 Sep 2015 02:59:00 -0000 Message-ID: <20150925025924.128650.qmail@sourceware.org> From: scox@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] scox/globalstate: Add initial multiple client support. X-Git-Refname: refs/heads/scox/globalstate X-Git-Reftype: branch X-Git-Oldrev: 53b72aacff3f6171dec3dada5943526912940299 X-Git-Newrev: 589dd9c8abac87fa8306733f9e6b56af97e739fb X-SW-Source: 2015-q3/txt/msg00047.txt.bz2 List-Id: The branch, scox/globalstate has been updated via 589dd9c8abac87fa8306733f9e6b56af97e739fb (commit) from 53b72aacff3f6171dec3dada5943526912940299 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 589dd9c8abac87fa8306733f9e6b56af97e739fb Author: Stan Cox Date: Thu Sep 24 22:57:27 2015 -0400 Add initial multiple client support. * event-loop.c (delete_file_handler): Add delete_client_state. * mem-break.c (has_client_breakpoint_at): New. * remote-utils.c (get_listen_desc): New. * server.c (get_client_state, set_client_state) * server.h (last_status, last_ptid, current_thread) ----------------------------------------------------------------------- Summary of changes: gdb/gdbserver/ChangeLog | 30 ++ gdb/gdbserver/event-loop.c | 43 ++ gdb/gdbserver/mem-break.c | 30 ++ gdb/gdbserver/mem-break.h | 4 + gdb/gdbserver/remote-utils.c | 70 ++-- gdb/gdbserver/remote-utils.h | 3 +- gdb/gdbserver/server.c | 610 +++++++++++++++++++++++++++-- gdb/gdbserver/server.h | 52 +++- gdb/testsuite/gdb.server/multi-client.exp | 166 ++++++++ 9 files changed, 948 insertions(+), 60 deletions(-) create mode 100644 gdb/testsuite/gdb.server/multi-client.exp First 500 lines of diff: diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index cf961e2..6c80e10 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,33 @@ +2015-09-24 Stan Cox + + * server.c (get_client_state, set_client_state) + (delete_client_breakpoint, free_client_state, add_client_by_pid) + (add_client_by_exe, get_first_client_fd, have_multiple_clients) + (delete_client_state, add_client_breakpoint) New for managing + client/server structures. + (pending_types, get_pack_type, resolve_waiter, setup_multiplexing) + (setup_multiplexing, do_multiplexing) New for managing run state + of clients. + (start_inferior): Add client to list. + (handle_monitor_command): Add 'client status' + (process_serial_event): Manage multiple client connections. Call + (setup,do)_multiplexing. + + * server.h (last_status, last_ptid, current_thread) + (exit_requested): Add union as access macro alternative + (client_breakpoint): New struct. + (file_desc, executable, packet_type, last_packet_type, pending): New. + + * event-loop.c (delete_file_handler): Add delete_client_state. + (handle_file_event): Reset file descriptor for multiple clients. + (wait_for_event): Handle additional client connections. + + * mem-break.c (has_client_breakpoint_at): New. + + * remote-utils.c (get_listen_desc): New. + (handle_accept_event): Unset noack_mode. + (write_prim, write, read_prim, readchar, getpkt): Add file desc parm. + 2015-09-12 Stan Cox * gdbthread.h (last_status): Rename last_waitstatus to avoid conflict diff --git a/gdb/gdbserver/event-loop.c b/gdb/gdbserver/event-loop.c index dd07093..3724cd7 100644 --- a/gdb/gdbserver/event-loop.c +++ b/gdb/gdbserver/event-loop.c @@ -385,6 +385,8 @@ delete_file_handler (gdb_fildes_t fd) ; prev_ptr->next_file = file_ptr->next_file; } + + delete_client_state (fd); free (file_ptr); } @@ -425,6 +427,9 @@ handle_file_event (gdb_fildes_t event_file_desc) /* If there was a match, then call the handler. */ if (mask != 0) { + /* Don't change client states if we have multiple clients */ + if (have_multiple_clients ()) + set_client_state (file_ptr->fd); if ((*file_ptr->proc) (file_ptr->error, file_ptr->client_data) < 0) return -1; @@ -465,6 +470,38 @@ wait_for_event (void) file_handler *file_ptr; int num_found = 0; + /* Do we have another client? */ + fd_set conn_fd_set; + struct timeval timeout; + FD_ZERO(&conn_fd_set); + FD_SET(get_listen_desc(),&conn_fd_set); + timeout.tv_sec = 0; + timeout.tv_usec = 10; + num_found = select (FD_SETSIZE, &conn_fd_set, NULL, NULL, &timeout); + if (debug_threads > 1) + fprintf (stderr,"%s select fd=%d found=%d\n",__FUNCTION__,get_listen_desc(),num_found); + if (num_found > 0) + { + int i; + for (i = 1; i < FD_SETSIZE; ++i) + if (FD_ISSET (i, &conn_fd_set)) + { + if (i == get_listen_desc()) + { + int handle_accept_event (int, gdb_client_data); + if (debug_threads > 1) + fprintf (stderr,"%s in select idx %d\n",__FUNCTION__,i); + /* instead of using gdb_event just setup the connection "by hand" */ + handle_accept_event (0, NULL); + add_file_handler (get_remote_desc(), handle_serial_event, get_client_state()); + } + else + if (debug_threads > 1) + fprintf (stderr,"%s data arrived on existing connection %d fd=%d\n", __FUNCTION__, i,get_listen_desc()); + } + } + /* */ + /* Make sure all output is done before getting another event. */ fflush (stdout); fflush (stderr); @@ -520,8 +557,14 @@ wait_for_event (void) if (file_ptr->ready_mask == 0) { + int handle_accept_event (int err, gdb_client_data client_data); gdb_event *file_event_ptr = create_file_event (file_ptr->fd); + if (debug_threads > 1) + { + fprintf (stderr,"%s #fds=%d\n",__FUNCTION__,gdb_notifier.num_fds); + fprintf(stderr,"%s create_file_event for %d %#lx %#lx %#lx %#lx\n",__FUNCTION__,file_event_ptr->fd,(long unsigned int)file_ptr->proc,(long unsigned int)handle_file_event,(long unsigned int)handle_serial_event,(long unsigned int)handle_accept_event); + } QUEUE_enque (gdb_event_p, event_queue, file_event_ptr); } file_ptr->ready_mask = mask; diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c index 9356741..138e8e0 100644 --- a/gdb/gdbserver/mem-break.c +++ b/gdb/gdbserver/mem-break.c @@ -293,6 +293,36 @@ find_raw_breakpoint_at (CORE_ADDR addr, enum raw_bkpt_type type, int size) return NULL; } +/* Is there a low-level breakpoint at address ADDR? */ + +int +has_client_breakpoint_at (CORE_ADDR addr) +{ + client_state *cs = get_client_state (); + + struct client_breakpoint *cb; + if (debug_threads) + debug_printf ("%s:%d fd=%d addr=%#lx\n", __FUNCTION__, __LINE__, cs->file_desc, (long unsigned)addr); + for (cb = cs->client_breakpoints; cb != NULL; cb = cb->next) + if (debug_threads) + debug_printf ("%s:%d %d breakpoint at %#lx\n", __FUNCTION__, __LINE__, cs->file_desc, (long unsigned)cb->addr); + + // for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next) + { + // if (addr >= bp->pc && addr <= bp->pc + 8 && cs->ss->last_status.kind == TARGET_WAITKIND_STOPPED + // && cs->ss->last_status.value.sig == GDB_SIGNAL_TRAP) + for (cb = cs->client_breakpoints; cb != NULL; cb = cb->next) + // TODO improve this; pc might be one insn ahead of break. + { + debug_printf ("%s:%d addr=%#lx pb->pc %#lx in range? %d\n", __FUNCTION__, __LINE__, (long unsigned) addr, (long unsigned)cb->addr, addr >= cb->addr && addr <= cb->addr + 8); + if (addr >= cb->addr && addr <= cb->addr + 8) + return 1; + } + } + return 0; +} + + /* See mem-break.h. */ int diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h index b5a3208..9f737d0 100644 --- a/gdb/gdbserver/mem-break.h +++ b/gdb/gdbserver/mem-break.h @@ -245,6 +245,10 @@ void uninsert_fast_tracepoint_jumps_at (CORE_ADDR pc); void reinsert_fast_tracepoint_jumps_at (CORE_ADDR where); +/* Does a client have a breakpoint at addr? */ + +int has_client_breakpoint_at (CORE_ADDR addr); + /* Insert a memory breakpoint. */ int insert_memory_breakpoint (struct raw_breakpoint *bp); diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index 67268ea..d2b3b85 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -88,7 +88,7 @@ enum { Either NOT_SCHEDULED or the callback id. */ static int readchar_callback = NOT_SCHEDULED; -static int readchar (void); +static int readchar (gdb_fildes_t); static void reset_readchar (void); static void reschedule (void); @@ -136,6 +136,12 @@ set_remote_desc (gdb_fildes_t fd) } int +get_listen_desc () +{ + return listen_desc; +} + +int gdb_connected (void) { return remote_desc != INVALID_DESCRIPTOR; @@ -163,7 +169,7 @@ enable_async_notification (int fd) #endif } -static int +int handle_accept_event (int err, gdb_client_data client_data) { struct sockaddr_in sockaddr; @@ -172,11 +178,14 @@ handle_accept_event (int err, gdb_client_data client_data) if (debug_threads) debug_printf ("handling possible accept event\n"); + noack_mode = 0; tmp = sizeof (sockaddr); remote_desc = accept (listen_desc, (struct sockaddr *) &sockaddr, &tmp); if (remote_desc == -1) perror_with_name ("Accept failed"); + set_client_state (remote_desc); + /* Enable TCP keep alive process. */ tmp = 1; setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE, @@ -193,7 +202,8 @@ handle_accept_event (int err, gdb_client_data client_data) exits when the remote side dies. */ #endif - if (run_once) + /* TODO check this */ + if (0 && run_once) { #ifndef USE_WIN32API close (listen_desc); /* No longer need this */ @@ -204,7 +214,8 @@ handle_accept_event (int err, gdb_client_data client_data) /* Even if !RUN_ONCE no longer notice new connections. Still keep the descriptor open for add_file_handler to wait for a new connection. */ - delete_file_handler (listen_desc); + // TODO check this + // delete_file_handler (listen_desc); /* Convert IP address to string. */ fprintf (stderr, "Remote debugging from host %s\n", @@ -601,12 +612,12 @@ read_ptid (char *buf, char **obuf) This may return less than COUNT. */ static int -write_prim (const void *buf, int count) +write_prim (gdb_fildes_t fd, const void *buf, int count) { if (remote_connection_is_stdio ()) return write (fileno (stdout), buf, count); else - return write (remote_desc, buf, count); + return write (fd, buf, count); } /* Read COUNT bytes from the client and store in BUF. @@ -614,12 +625,12 @@ write_prim (const void *buf, int count) This may return less than COUNT. */ static int -read_prim (void *buf, int count) +read_prim (gdb_fildes_t fd, void *buf, int count) { if (remote_connection_is_stdio ()) return read (fileno (stdin), buf, count); else - return read (remote_desc, buf, count); + return read (fd, buf, count); } /* Send a packet to the remote machine, with error checking. @@ -634,6 +645,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif) char *buf2; char *p; int cc; + client_state *cs = get_client_state(); buf2 = xmalloc (strlen ("$") + cnt + strlen ("#nn") + 1); @@ -659,7 +671,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif) do { - if (write_prim (buf2, p - buf2) != p - buf2) + if (write_prim (cs->file_desc, buf2, p - buf2) != p - buf2) { perror ("putpkt(write)"); free (buf2); @@ -672,9 +684,9 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif) if (remote_debug) { if (is_notif) - fprintf (stderr, "putpkt (\"%s\"); [notif]\n", buf2); + fprintf (stderr, "putpkt/%d (\"%s\"); [notif]\n", cs->file_desc, buf2); else - fprintf (stderr, "putpkt (\"%s\"); [noack mode]\n", buf2); + fprintf (stderr, "putpkt/%d (\"%s\"); [noack mode]\n", cs->file_desc, buf2); fflush (stderr); } break; @@ -682,11 +694,11 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif) if (remote_debug) { - fprintf (stderr, "putpkt (\"%s\"); [looking for ack]\n", buf2); + fprintf (stderr, "putpkt/%d (\"%s\"); [looking for ack]\n", cs->file_desc, buf2); fflush (stderr); } - cc = readchar (); + cc = readchar (cs->file_desc); if (cc < 0) { @@ -754,7 +766,7 @@ input_interrupt (int unused) int cc; char c = 0; - cc = read_prim (&c, 1); + cc = read_prim (remote_desc, &c, 1); if (cc == 0) { @@ -877,13 +889,13 @@ initialize_async_io (void) /* Returns next char from remote GDB. -1 if error. */ static int -readchar (void) +readchar (gdb_fildes_t fd) { int ch; if (readchar_bufcnt == 0) { - readchar_bufcnt = read_prim (readchar_buf, sizeof (readchar_buf)); + readchar_bufcnt = read_prim (fd, readchar_buf, sizeof (readchar_buf)); if (readchar_bufcnt <= 0) { @@ -949,7 +961,7 @@ reschedule (void) and store it in BUF. Returns length of packet, or negative if error. */ int -getpkt (char *buf) +getpkt (gdb_fildes_t fd, char *buf) { char *bp; unsigned char csum, c1, c2; @@ -961,7 +973,7 @@ getpkt (char *buf) while (1) { - c = readchar (); + c = readchar (fd); if (c == '$') break; if (remote_debug) @@ -977,7 +989,7 @@ getpkt (char *buf) bp = buf; while (1) { - c = readchar (); + c = readchar (fd); if (c < 0) return -1; if (c == '#') @@ -987,8 +999,8 @@ getpkt (char *buf) } *bp = 0; - c1 = fromhex (readchar ()); - c2 = fromhex (readchar ()); + c1 = fromhex (readchar (fd)); + c2 = fromhex (readchar (fd)); if (csum == (c1 << 4) + c2) break; @@ -1005,7 +1017,7 @@ getpkt (char *buf) fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", (c1 << 4) + c2, csum, buf); - if (write_prim ("-", 1) != 1) + if (write_prim (fd, "-", 1) != 1) return -1; } @@ -1013,11 +1025,11 @@ getpkt (char *buf) { if (remote_debug) { - fprintf (stderr, "getpkt (\"%s\"); [sending ack] \n", buf); + fprintf (stderr, "getpkt/%d (\"%s\"); [sending ack] \n", fd, buf); fflush (stderr); } - if (write_prim ("+", 1) != 1) + if (write_prim (fd, "+", 1) != 1) return -1; if (remote_debug) @@ -1030,7 +1042,7 @@ getpkt (char *buf) { if (remote_debug) { - fprintf (stderr, "getpkt (\"%s\"); [no ack sent] \n", buf); + fprintf (stderr, "getpkt/%d (\"%s\"); [no ack sent] \n", fd, buf); fflush (stderr); } } @@ -1451,7 +1463,7 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb) return -1; /* FIXME: Eventually add buffer overflow checking (to getpkt?) */ - len = getpkt (own_buf); + len = getpkt (remote_desc, own_buf); if (len < 0) return -1; @@ -1475,7 +1487,7 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb) free (mem_buffer); if (putpkt (own_buf) < 0) return -1; - len = getpkt (own_buf); + len = getpkt (remote_desc, own_buf); if (len < 0) return -1; } @@ -1534,7 +1546,7 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc) return -1; /* FIXME: Eventually add buffer overflow checking (to getpkt?) */ - len = getpkt (own_buf); + len = getpkt (remote_desc, own_buf); if (len < 0) return -1; @@ -1577,7 +1589,7 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc) free (mem_buffer); if (putpkt (own_buf) < 0) return -1; - len = getpkt (own_buf); + len = getpkt (remote_desc, own_buf); if (len < 0) return -1; } diff --git a/gdb/gdbserver/remote-utils.h b/gdb/gdbserver/remote-utils.h index 2a1c62f..32f0b52 100644 --- a/gdb/gdbserver/remote-utils.h +++ b/gdb/gdbserver/remote-utils.h @@ -25,6 +25,7 @@ extern int transport_is_reliable; int get_remote_desc (void); void set_remote_desc (gdb_fildes_t); +int get_listen_desc (void); int gdb_connected (void); @@ -37,7 +38,7 @@ char *write_ptid (char *buf, ptid_t ptid); int putpkt (char *buf); int putpkt_binary (char *buf, int len); int putpkt_notif (char *buf); -int getpkt (char *buf); +int getpkt (gdb_fildes_t,char *buf); void remote_prepare (char *name); void remote_open (char *name); void remote_close (void); diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 9838a6f..07828c2 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -83,33 +83,520 @@ DEFINE_QUEUE_P (notif_event_p); static struct client_states client_states; +static void handle_status (char *); + + +/* Return the current client state */ + +extern inline client_state* +get_client_state (void) +{ + return client_states.current_cs; +} + /* Add a new client state for fd or return if found */ client_state * set_client_state (gdb_fildes_t fd) { - if (client_states.first == NULL) +/* States: + * fd = -1 add initial client state + * fd = F add client state for fd F + */ + + client_state *csidx; + + /* add/return initial client state */ hooks/post-receive -- Repository for Project Archer.