From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1491 invoked by alias); 14 Oct 2015 15:36:39 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 1371 invoked by uid 89); 14 Oct 2015 15:36:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 14 Oct 2015 15:36:36 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 6C54B74 for ; Wed, 14 Oct 2015 15:28:12 +0000 (UTC) Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t9EFS6Dd016846 for ; Wed, 14 Oct 2015 11:28:11 -0400 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 04/18] gdbserver crash running gdb.threads/non-ldr-exc-1.exp Date: Wed, 14 Oct 2015 15:36:00 -0000 Message-Id: <1444836486-25679-5-git-send-email-palves@redhat.com> In-Reply-To: <1444836486-25679-1-git-send-email-palves@redhat.com> References: <1444836486-25679-1-git-send-email-palves@redhat.com> X-SW-Source: 2015-10/txt/msg00225.txt.bz2 This fixes a gdbserver crash when running gdb.threads/non-ldr-exc-1.exp with "maint set target-non-stop on". The problem is that qSymbol is called when gdbserver has current_thread == NULL. gdb/gdbserver/ChangeLog: 2015-10-14 Pedro Alves * gdbthread.h (find_any_thread_of_pid): Declare. * inferiors.c (thread_of_pid, find_any_thread_of_pid): New functions. * server.c (handle_query): If current_thread is NULL, look for another thread of the selected process. --- gdb/gdbserver/gdbthread.h | 4 ++++ gdb/gdbserver/inferiors.c | 23 +++++++++++++++++++++++ gdb/gdbserver/server.c | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h index d6959f4..0510419 100644 --- a/gdb/gdbserver/gdbthread.h +++ b/gdb/gdbserver/gdbthread.h @@ -80,6 +80,10 @@ struct thread_info *get_first_thread (void); struct thread_info *find_thread_ptid (ptid_t ptid); +/* Find any thread of the PID process. Returns NULL if none is + found. */ +struct thread_info *find_any_thread_of_pid (int pid); + /* Get current thread ID (Linux task ID). */ #define current_ptid (current_thread->entry.id) diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c index 21f45fa..84f5b7c 100644 --- a/gdb/gdbserver/inferiors.c +++ b/gdb/gdbserver/inferiors.c @@ -141,6 +141,29 @@ find_thread_ptid (ptid_t ptid) return (struct thread_info *) find_inferior_id (&all_threads, ptid); } +/* Helper for find_any_thread_of_pid. Returns true if a thread + matches a PID. */ + +static int +thread_of_pid (struct inferior_list_entry *entry, void *pid_p) +{ + int pid = *(int *) pid_p; + + return (ptid_get_pid (entry->id) == pid); +} + +/* See gdbthread.h. */ + +struct thread_info * +find_any_thread_of_pid (int pid) +{ + struct inferior_list_entry *entry; + + entry = find_inferior (&all_threads, thread_of_pid, &pid); + + return (struct thread_info *) entry; +} + ptid_t gdb_id_to_thread_id (ptid_t gdb_id) { diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index e25b7c7..ec52f84 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -1971,6 +1971,27 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) if (strcmp ("qSymbol::", own_buf) == 0) { + struct thread_info *save_thread = current_thread; + + /* For qSymbol, GDB only changes the current thread if the + previous current thread was of a different process. So if + the previous thread is gone, we need to pick another one of + the same process. This can happen e.g., if we followed an + exec in a non-leader thread. */ + if (current_thread == NULL) + { + current_thread = find_any_thread_of_pid (ptid_get_pid (general_thread)); + + /* Just in case, if we didn't find a thread, then bail out + instead of crashing. */ + if (current_thread == NULL) + { + write_enn (own_buf); + current_thread = save_thread; + return; + } + } + /* GDB is suggesting new symbols have been loaded. This may mean a new shared library has been detected as loaded, so take the opportunity to check if breakpoints we think are @@ -1989,6 +2010,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) if (current_thread != NULL && the_target->look_up_symbols != NULL) (*the_target->look_up_symbols) (); + current_thread = save_thread; + strcpy (own_buf, "OK"); return; } -- 1.9.3