From patchwork Tue Nov 29 15:07:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthias Pfaller X-Patchwork-Id: 18042 Received: (qmail 4994 invoked by alias); 29 Nov 2016 15:07:19 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 4818 invoked by uid 89); 29 Nov 2016 15:07:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: =?ISO-8859-1?Q?Yes, score=6.0 required=5.0 tests=AWL, BAYES_99, BAYES_999, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=8:sc, Amtsgericht, amtsgericht, 8:h=c3?= X-HELO: mail.marco.de Received: from mail.marco.de (HELO mail.marco.de) (93.104.246.50) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 29 Nov 2016 15:07:06 +0000 Received: from mailbox.marco.de (mailbox [10.1.2.4]) by mail.marco.de (Postfix) with ESMTP id 671747622C1; Tue, 29 Nov 2016 16:07:04 +0100 (CET) Received: from [10.1.1.28] (rhea.dachau.marco.de [10.1.1.28]) (Authenticated sender: leo) by mailbox.marco.de (Postfix) with ESMTPSA; Tue, 29 Nov 2016 16:07:04 +0100 (CET) To: gdb-patches@sourceware.org, lgustavo@codesourcery.com From: Matthias Pfaller Subject: target remote and multiprocess+ Message-ID: <583D9998.5030603@marco.de> Date: Tue, 29 Nov 2016 16:07:04 +0100 User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 X-IsSubscribed: yes Hi, This patch does: (1) make "multiprocess+;" work with "target remote" (2) stop inferiors only for the event thread when a break or watch point is hit (3) stop new inferiors only when global break or watch points are in place This makes it possible to debug an embedded target where gdbserver is running as native thread on the target. The target has to report the threadlist as an inferiorlist with one thread per inferior. That way one can context switch break and watch points and halt only the thread to be debugged. Without (2) and (3) the gdbstub on the target would get stopped when connecting... Per advice of Luis Machado I did run make check >check.out 2>&1 and make check-gdb RUNTESTFLAGS="--target_board native-gdbserver" >check2.out 2>&1 I then did a "grep FAILED | sort" on the outputs of an unmodified gdb-7.12 and a gdb-7.12 bult with my patch. A diff between both sets of output didn't show up any new FAILED lines. regards, Matthias --- ../orig/gdb/breakpoint.c +++ ./gdb/breakpoint.c --- ../orig/gdb/infcmd.c +++ ./gdb/infcmd.c @@ -2741,7 +2741,7 @@ struct thread_info *lowest = inferior_thread (); int pid = current_inferior ()->pid; - stop_all_threads (); + stop_all_threads (inferior); /* It's not defined which thread will report the attach stop. For consistency, always select the thread with @@ -2920,6 +2920,28 @@ attach_post_wait (args, from_tty, mode); } +/* Helper function for any_global_breakpoint. If B is a global + break or catch point, return 1 (which will make + 'breakpoint_find_if' return). Otherwise, return 0. */ + +static int +any_global_breakpoint_1 (struct breakpoint *b, + void *data) +{ + if (b->enable_state == bp_enabled && b->thread == -1) + return 1; + else + return 0; +} + +static int +any_global_breakpoint (void) +{ + struct breakpoint *b = breakpoint_find_if (any_global_breakpoint_1, NULL); + + return b != NULL; +} + /* We had just found out that the target was already attached to an inferior. PTID points at a thread of this new inferior, that is the most likely to be stopped right now, but not necessarily so. @@ -2948,7 +2970,9 @@ /* When we "notice" a new inferior we need to do all the things we would normally do if we had just attached to it. */ - if (is_executing (inferior_ptid)) + if (!leave_running && + any_global_breakpoint () && + is_executing (inferior_ptid)) { struct attach_command_continuation_args *a; struct inferior *inferior = current_inferior (); --- ../orig/gdb/inferior.c +++ ./gdb/inferior.c @@ -320,13 +320,27 @@ void discard_all_inferiors (void) { - struct inferior *inf; + struct inferior *inf, *infnext; - for (inf = inferior_list; inf; inf = inf->next) + for (inf = inferior_list; inf; inf = infnext) { - if (inf->pid != 0) - exit_inferior_silent (inf->pid); + infnext = inf->next; + + if (inf->num == 1) + { + if (inf->pid != 0) + exit_inferior_1 (inf, 1); + } + else + delete_inferior (inf); } + + inferior_ptid = null_ptid; + inferior_list->pid = 0; + set_current_inferior (inferior_list); + switch_to_thread (null_ptid); + + highest_inferior_num = inferior_list->num; } struct inferior * --- ../orig/gdb/infrun.c +++ ./gdb/infrun.c @@ -2584,7 +2584,7 @@ /* Fallback to stepping over the breakpoint in-line. */ if (target_is_non_stop_p ()) - stop_all_threads (); + stop_all_threads (tp->inf); set_step_over_info (get_regcache_aspace (regcache), regcache_read_pc (regcache), 0, tp->global_num); @@ -4496,7 +4496,7 @@ /* See infrun.h. */ void -stop_all_threads (void) +stop_all_threads (struct inferior *inferior) { /* We may need multiple passes to discover all threads. */ int pass; @@ -4509,6 +4509,11 @@ if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads\n"); + /* With global break points we have always to + stop all threads of all inferiors. */ + if (gdbarch_has_global_breakpoints (target_gdbarch ())) + inferior = NULL; + entry_ptid = inferior_ptid; old_chain = make_cleanup (switch_to_thread_cleanup, &entry_ptid); @@ -4539,6 +4544,8 @@ to tell the target to stop. */ ALL_NON_EXITED_THREADS (t) { + if (inferior != NULL && inferior != t->inf) + continue; if (t->executing) { /* If already stopping, don't request a stop again. @@ -5442,7 +5449,7 @@ ALL_NON_EXITED_THREADS (tp) { - if (tp == event_thread) + if (tp == event_thread || tp->inf != event_thread->inf) { if (debug_infrun) fprintf_unfiltered (gdb_stdlog, @@ -7705,7 +7712,7 @@ /* If all-stop, but the target is always in non-stop mode, stop all threads now that we're presenting the stop to the user. */ if (!non_stop && target_is_non_stop_p ()) - stop_all_threads (); + stop_all_threads (NULL); } /* Like keep_going, but passes the signal to the inferior, even if the @@ -7821,7 +7828,7 @@ we're about to step over, otherwise other threads could miss it. */ if (step_over_info_valid_p () && target_is_non_stop_p ()) - stop_all_threads (); + stop_all_threads (ecs->event_thread->inf); /* Stop stepping if inserting breakpoints fails. */ TRY --- ../orig/gdb/infrun.h +++ ./gdb/infrun.h @@ -110,8 +110,12 @@ extern void set_last_target_status (ptid_t ptid, struct target_waitstatus status); -/* Stop all threads. Only returns after everything is halted. */ -extern void stop_all_threads (void); +/* Stop all threads belonging to inf. + When called with inf == NULL, stop all threads of all inferiors. + With gdbarch_has_global_breakpoints () is true, always stop all + threads of all inferiors. + Only returns after everything is halted. */ +extern void stop_all_threads (struct inferior *inf); extern void prepare_for_detach (void); --- ../orig/gdb/remote.c +++ ./gdb/remote.c @@ -1789,8 +1789,24 @@ /* In the traditional debugging scenario, there's a 1-1 match between program/address spaces. We simply bind the inferior to the program space's address space. */ - inf = current_inferior (); - inferior_appeared (inf, pid); + + inf = find_inferior_id (pid); + if (inf == NULL) + { + if (current_inferior () ->pid == 0) + { + inf = current_inferior (); + inferior_appeared (inf, pid); + } + else + { + inf = add_inferior (pid); + inf->aspace = current_inferior () ->aspace; + inf->pspace = current_program_space; + inf->gdbarch = current_inferior () ->gdbarch; + copy_inferior_target_desc_info(inf, current_inferior ()); + } + } } inf->attach_flag = attached; @@ -1801,6 +1817,10 @@ if (try_open_exec && get_exec_file (0) == NULL) exec_file_locate_attach (pid, 0, 1); + set_current_inferior (inf); + + inferior_ptid = pid_to_ptid (pid); + return inf; } @@ -1902,6 +1922,9 @@ /* This is really a new thread. Add it. */ remote_add_thread (currthread, running, executing); + if (ptid_is_pid (inferior_ptid) + && pid == ptid_get_pid (inferior_ptid)) + inferior_ptid = currthread; /* If we found a new inferior, let the common code do whatever it needs to with it (e.g., read shared libraries, insert @@ -3937,7 +3960,7 @@ the inferiors. */ if (!non_stop) { - stop_all_threads (); + stop_all_threads (NULL); /* If all threads of an inferior were already stopped, we haven't setup the inferior yet. */