From patchwork Fri May 20 15:12:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 12419 Received: (qmail 68336 invoked by alias); 20 May 2016 15:13:08 -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 67880 invoked by uid 89); 20 May 2016 15:13:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=sk:proceed, Stop, lp X-HELO: mail-pa0-f66.google.com Received: from mail-pa0-f66.google.com (HELO mail-pa0-f66.google.com) (209.85.220.66) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 20 May 2016 15:13:03 +0000 Received: by mail-pa0-f66.google.com with SMTP id yl2so11194695pac.1 for ; Fri, 20 May 2016 08:13:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=Fy6on1BGGwUO/cc8PAO1TPb3Iz7IHarS/5Ipd32YT0c=; b=f0R4ysWr60jUM4dGHB5gNx9ePYDUn4fYVHAgYfI0M62w0BVdD4Vr1+Hox4OjgB47Yn RERoaNfCJwIOTJs+8hSixjas4cErKk9LufTOWqvVu0CSfCYs+Q7OShjT4sfFX+OR3L5C L8KONpAq6nYvvQN5ZjgdSbwNc4m7U+jmoh84akQLqO9sUDP5sLpYmfVjX1XyJGjq3hFC R/B8xUw7EyiWdTldA1hNCOVZoOfV2WA3e0DxeKnuLFmgs9s+2UtgySpUMZDDXdovAYye HvotKk8/FJGvKYSBAvTgpPOsDyuzxJy668qbuQg7tn7qaX1lOYUD1eoXAgHRl+dTsC6N m/9w== X-Gm-Message-State: AOPr4FVZtTRTHfTYAkEELc6SusjYu87U6bVlX7Ft+ivspKeKjbOkk3+wtbQZkm/fT1oBTA== X-Received: by 10.66.235.66 with SMTP id uk2mr5551908pac.83.1463757181184; Fri, 20 May 2016 08:13:01 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com (gcc113.osuosl.org. [140.211.9.71]) by smtp.gmail.com with ESMTPSA id p80sm27985272pfj.58.2016.05.20.08.12.59 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 20 May 2016 08:13:00 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 7/8] Use reinsert_breakpoint for vCont;s Date: Fri, 20 May 2016 16:12:40 +0100 Message-Id: <1463757161-25850-8-git-send-email-yao.qi@linaro.org> In-Reply-To: <1463757161-25850-1-git-send-email-yao.qi@linaro.org> References: <1463757161-25850-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes This patch is to teach GDBserver using software single step to handle vCont;s. Simply speaking, if the thread's resume request is resume_step, install reinsert breakpoint at the next pcs when GDBserver is about to resume threads. These reinsert breakpoints of a thread are removed, when GDBserver gets an event from that thread. Note that GDBserver may or may not report this event back to GDB. gdb/gdbserver: 2016-05-20 Yao Qi * linux-low.c (resume_stopped_resumed_lwps): If resume request is resume_step, either set step to 1 or assert that reinsert breakpoints are installed. (linux_wait_1): Stop all threads, remove reinsert breakpoints, and unstop them. (linux_resume_one_thread): If resume request is resume_step, either set step to 1 or assert that reinsert breakpoints are installed. (linux_resume): Install reinsert breakpoints if the thread is requested to resume_step. (proceed_one_lwp): If resume request is resume_step, either set step to 1 or assert that reinsert breakpoints are installed. (proceed_all_lwps): Install reinsert breakpoints if the thread is requested to resume_step. --- gdb/gdbserver/linux-low.c | 125 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 4 deletions(-) diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index d5f7097..22cf51a 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -2526,7 +2526,18 @@ resume_stopped_resumed_lwps (struct inferior_list_entry *entry) && !lp->status_pending_p && thread->last_status.kind == TARGET_WAITKIND_IGNORE) { - int step = thread->last_resume_kind == resume_step; + int step = 0; + + if (thread->last_resume_kind == resume_step) + { + if (can_hardware_single_step ()) + step = 1; + else + { + /* GDBserver must insert reinsert breakpoint for vCont;s. */ + gdb_assert (has_reinsert_breakpoints (thread)); + } + } if (debug_threads) debug_printf ("RSRL: resuming stopped-resumed LWP %s at %s: step=%d\n", @@ -3477,6 +3488,18 @@ linux_wait_1 (ptid_t ptid, return ignore_event (ourstatus); } + /* Remove reinsert breakpoints for resume_step. */ + if (can_software_single_step () + && current_thread->last_resume_kind == resume_step + && has_reinsert_breakpoints (current_thread)) + { + stop_all_lwps (1, event_child); + + delete_reinsert_breakpoints (current_ptid); + + unstop_all_lwps (1, event_child); + } + /* Note that all addresses are always "out of the step range" when there's no range to begin with. */ in_step_range = lwp_in_step_range (event_child); @@ -4796,7 +4819,6 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg) { struct thread_info *thread = (struct thread_info *) entry; struct lwp_info *lwp = get_thread_lwp (thread); - int step; int leave_all_stopped = * (int *) arg; int leave_pending; @@ -4865,10 +4887,22 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg) if (!leave_pending) { + int step = 0; + if (debug_threads) debug_printf ("resuming LWP %ld\n", lwpid_of (thread)); - step = (lwp->resume->kind == resume_step); + if (lwp->resume->kind == resume_step) + { + if (can_hardware_single_step ()) + step = 1; + else + { + /* GDBserver must insert reinsert breakpoint for vCont;s. */ + gdb_assert (has_reinsert_breakpoints (thread)); + } + } + linux_resume_one_lwp (lwp, step, lwp->resume->sig, NULL); } else @@ -4909,6 +4943,7 @@ linux_resume (struct thread_resume *resume_info, size_t n) struct thread_info *need_step_over = NULL; int any_pending; int leave_all_stopped; + int resume_step_is_handled = 0; if (debug_threads) { @@ -4952,12 +4987,57 @@ linux_resume (struct thread_resume *resume_info, size_t n) debug_printf ("Resuming, no pending status or step over needed\n"); } + /* Before we resume the threads, if resume_step is requested by GDB, + stop all threads and install reinsert breakpoints. */ + if (!leave_all_stopped && can_software_single_step ()) + { + struct inferior_list_entry *inf, *tmp; + + if (debug_threads) + debug_printf ("Handle resume_step.\n"); + + ALL_INFERIORS (&all_threads, inf, tmp) + { + struct thread_info *thread = (struct thread_info *) inf; + struct lwp_info *lwp = get_thread_lwp (thread); + + if (lwp->resume != NULL && lwp->resume->kind == resume_step) + { + struct thread_info *saved_thread; + + if (!resume_step_is_handled) + { + stop_all_lwps (0, NULL); + + if (debug_threads) + debug_printf ("Done stopping all threads.\n"); + + resume_step_is_handled = 1; + } + + saved_thread = current_thread; + current_thread = thread; + install_software_single_step_breakpoints (lwp); + current_thread = saved_thread; + + if (debug_threads) + debug_printf ("Insert breakpoint for resume_step LWP %ld\n", + lwpid_of (thread)); + } + } + + if (debug_threads) + debug_printf ("Handle resume_step. Done\n"); + } + /* Even if we're leaving threads stopped, queue all signals we'd otherwise deliver. */ find_inferior (&all_threads, linux_resume_one_thread, &leave_all_stopped); if (need_step_over) start_step_over (get_thread_lwp (need_step_over)); + else if (resume_step_is_handled) + unstop_all_lwps (0, NULL); if (debug_threads) { @@ -5054,7 +5134,14 @@ proceed_one_lwp (struct inferior_list_entry *entry, void *except) if (debug_threads) debug_printf (" stepping LWP %ld, client wants it stepping\n", lwpid_of (thread)); - step = 1; + + if (can_hardware_single_step ()) + step = 1; + else + { + /* GDBserver must insert reinsert breakpoint for vCont;s. */ + gdb_assert (has_reinsert_breakpoints (thread)); + } } else if (lwp->bp_reinsert != 0) { @@ -5124,6 +5211,36 @@ proceed_all_lwps (void) if (debug_threads) debug_printf ("Proceeding, no step-over needed\n"); + /* Re-install the reinsert breakpoints on software single step target + if the client wants it step. */ + if (can_software_single_step ()) + { + struct inferior_list_entry *inf, *tmp; + + ALL_INFERIORS (&all_threads, inf, tmp) + { + struct thread_info *thread = (struct thread_info *) inf; + + if (thread->last_resume_kind == resume_step) + { + struct lwp_info *lwp = get_thread_lwp (thread); + struct thread_info *saved_thread; + + saved_thread = current_thread; + current_thread = thread; + + if (!has_reinsert_breakpoints (thread)) + install_software_single_step_breakpoints (lwp); + + current_thread = saved_thread; + + if (debug_threads) + debug_printf ("Insert breakpoint for resume_step LWP %ld\n", + lwpid_of (thread)); + } + } + } + find_inferior (&all_threads, proceed_one_lwp, NULL); }