From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 70791 invoked by alias); 24 Feb 2016 18:51:57 -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 70729 invoked by uid 89); 24 Feb 2016 18:51:57 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL,BAYES_00,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=no version=3.3.2 spammy=sk:siginfo, UD:si_signo, Returns, 185 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 24 Feb 2016 18:51:53 +0000 Received: from svr-orw-fem-06.mgc.mentorg.com ([147.34.97.120]) by relay1.mentorg.com with esmtp id 1aYeXO-0003eY-No from Luis_Gustavo@mentor.com ; Wed, 24 Feb 2016 10:51:50 -0800 Received: from [172.30.1.130] (147.34.91.1) by SVR-ORW-FEM-06.mgc.mentorg.com (147.34.97.120) with Microsoft SMTP Server id 14.3.224.2; Wed, 24 Feb 2016 10:51:47 -0800 Subject: Re: [PATCH] Handle MIPS Linux SIGTRAP siginfo.si_code values References: <1456332239-24007-1-git-send-email-palves@redhat.com> To: Pedro Alves , , "Maciej W. Rozycki" Reply-To: Luis Machado From: Luis Machado Message-ID: <56CDFBC1.3000500@codesourcery.com> Date: Wed, 24 Feb 2016 18:51:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 In-Reply-To: <1456332239-24007-1-git-send-email-palves@redhat.com> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2016-02/txt/msg00748.txt.bz2 On 02/24/2016 01:43 PM, Pedro Alves wrote: > This unbreaks pending/delayed breakpoints handling, as well as > hardware watchpoints, on MIPS. > > Ref: https://sourceware.org/ml/gdb-patches/2016-02/msg00681.html > > The MIPS kernel reports SI_KERNEL for all kernel generated traps, > instead of TRAP_BRKPT / TRAP_HWBKPT, but GDB isn't aware of this. > > Basically, this commit: > > - Folds watchpoints logic into check_stopped_by_breakpoint, and > renames it to save_stop_reason. > > - Adds GDB_ARCH_IS_TRAP_HWBKPT. > > - Makes MIPS set both GDB_ARCH_IS_TRAP_BRPT and > GDB_ARCH_IS_TRAP_HWBKPT to SI_KERNEL. In save_stop_reason, we > handle the case of the same si_code returning true for both > TRAP_BRPT and TRAP_HWBKPT by looking at what the debug registers > say. > > Tested on x86-64 Fedora 20, native and gdbserver. > > gdb/ChangeLog: > 2016-02-24 Pedro Alves > > * linux-nat.c (save_sigtrap) Delete. > (stop_wait_callback): Call save_stop_reason instead of > save_sigtrap. > (check_stopped_by_breakpoint): Rename to ... > (save_stop_reason): ... this. Bits of save_sigtrap folded here. > Use GDB_ARCH_IS_TRAP_HWBKPT and handle ambiguous > GDB_ARCH_IS_TRAP_BRKPT / GDB_ARCH_IS_TRAP_HWBKPT. Factor out > common code between the USE_SIGTRAP_SIGINFO and > !USE_SIGTRAP_SIGINFO blocks. > (linux_nat_filter_event): Call save_stop_reason instead of > save_sigtrap. > * nat/linux-ptrace.h: Check for both SI_KERNEL and TRAP_BRKPT > si_code for MIPS. > * nat/linux-ptrace.h: Fix "TRAP_HWBPT" typo in x86 table. Add > comments on MIPS behavior. > (GDB_ARCH_IS_TRAP_HWBKPT): Define for all archs. > > gdb/gdbserver/ChangeLog: > 2016-02-24 Pedro Alves > > * linux-low.c (check_stopped_by_breakpoint): Rename to ... > (save_stop_reason): ... this. Use GDB_ARCH_IS_TRAP_HWBKPT and > handle ambiguous GDB_ARCH_IS_TRAP_BRKPT / GDB_ARCH_IS_TRAP_HWBKPT. > Factor out common code between the USE_SIGTRAP_SIGINFO and > !USE_SIGTRAP_SIGINFO blocks. > (linux_low_filter_event): Call save_stop_reason instead of > check_stopped_by_breakpoint and check_stopped_by_watchpoint. > Update comments. > (linux_wait_1): Update comments. > --- > gdb/gdbserver/linux-low.c | 170 ++++++++++++++++++++-------------------------- > gdb/linux-nat.c | 149 ++++++++++++++++++++-------------------- > gdb/nat/linux-ptrace.h | 38 ++++++++--- > 3 files changed, 172 insertions(+), 185 deletions(-) > > diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c > index 8b025bd..b02ad31 100644 > --- a/gdb/gdbserver/linux-low.c > +++ b/gdb/gdbserver/linux-low.c > @@ -735,32 +735,16 @@ get_syscall_trapinfo (struct lwp_info *lwp, int *sysno, int *sysret) > current_thread = saved_thread; > } > > -/* This function should only be called if LWP got a SIGTRAP. > - The SIGTRAP could mean several things. > +static int check_stopped_by_watchpoint (struct lwp_info *child); > > - On i386, where decr_pc_after_break is non-zero: > - > - If we were single-stepping this process using PTRACE_SINGLESTEP, we > - will get only the one SIGTRAP. The value of $eip will be the next > - instruction. If the instruction we stepped over was a breakpoint, > - we need to decrement the PC. > - > - If we continue the process using PTRACE_CONT, we will get a > - SIGTRAP when we hit a breakpoint. The value of $eip will be > - the instruction after the breakpoint (i.e. needs to be > - decremented). If we report the SIGTRAP to GDB, we must also > - report the undecremented PC. If the breakpoint is removed, we > - must resume at the decremented PC. > - > - On a non-decr_pc_after_break machine with hardware or kernel > - single-step: > - > - If we either single-step a breakpoint instruction, or continue and > - hit a breakpoint instruction, our PC will point at the breakpoint > - instruction. */ > +/* Called when the LWP stopped for a signal/trap. If it stopped for a > + trap check what caused it (breakpoint, watchpoint, trace, etc.), > + and save the result in the LWP's stop_reason field. If it stopped > + for a breakpoint, decrement the PC if necessary on the lwp's > + architecture. Returns true if we now have the LWP's stop PC. */ > > static int > -check_stopped_by_breakpoint (struct lwp_info *lwp) > +save_stop_reason (struct lwp_info *lwp) > { > CORE_ADDR pc; > CORE_ADDR sw_breakpoint_pc; > @@ -785,56 +769,39 @@ check_stopped_by_breakpoint (struct lwp_info *lwp) > { > if (siginfo.si_signo == SIGTRAP) > { > - if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code)) > + if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code) > + && GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code)) > { > - if (debug_threads) > - { > - struct thread_info *thr = get_lwp_thread (lwp); > - > - debug_printf ("CSBB: %s stopped by software breakpoint\n", > - target_pid_to_str (ptid_of (thr))); > - } > - > - /* Back up the PC if necessary. */ > - if (pc != sw_breakpoint_pc) > - { > - struct regcache *regcache > - = get_thread_regcache (current_thread, 1); > - (*the_low_target.set_pc) (regcache, sw_breakpoint_pc); > - } > - > - lwp->stop_pc = sw_breakpoint_pc; > + /* The si_code is ambiguous on this arch -- check debug > + registers. */ > + if (!check_stopped_by_watchpoint (lwp)) > + lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; > + } > + else if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code)) > + { > + /* If we determine the LWP stopped for a SW breakpoint, > + trust it. Particularly don't check watchpoint > + registers, because at least on s390, we'd find > + stopped-by-watchpoint as long as there's a watchpoint > + set. */ > lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; > - current_thread = saved_thread; > - return 1; > } > - else if (siginfo.si_code == TRAP_HWBKPT) > + else if (GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code)) > { > - if (debug_threads) > - { > - struct thread_info *thr = get_lwp_thread (lwp); > - > - debug_printf ("CSBB: %s stopped by hardware " > - "breakpoint/watchpoint\n", > - target_pid_to_str (ptid_of (thr))); > - } > - > - lwp->stop_pc = pc; > - lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; > - current_thread = saved_thread; > - return 1; > + /* This can indicate either a hardware breakpoint or > + hardware watchpoint. Check debug registers. */ > + if (!check_stopped_by_watchpoint (lwp)) > + lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; > } > else if (siginfo.si_code == TRAP_TRACE) > { > - if (debug_threads) > - { > - struct thread_info *thr = get_lwp_thread (lwp); > - > - debug_printf ("CSBB: %s stopped by trace\n", > - target_pid_to_str (ptid_of (thr))); > - } > - > - lwp->stop_reason = TARGET_STOPPED_BY_SINGLE_STEP; > + /* We may have single stepped an instruction that > + triggered a watchpoint. In that case, on some > + architectures (such as x86), instead of TRAP_HWBKPT, > + si_code indicates TRAP_TRACE, and we need to check > + the debug registers separately. */ > + if (!check_stopped_by_watchpoint (lwp)) > + lwp->stop_reason = TARGET_STOPPED_BY_SINGLE_STEP; > } > } > } > @@ -845,6 +812,16 @@ check_stopped_by_breakpoint (struct lwp_info *lwp) > case we need to report the breakpoint PC. */ > if ((!lwp->stepping || lwp->stop_pc == sw_breakpoint_pc) > && (*the_low_target.breakpoint_at) (sw_breakpoint_pc)) > + lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; > + > + if (hardware_breakpoint_inserted_here (pc)) > + lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; > + > + if (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON) > + check_stopped_by_watchpoint (lp); > +#endif > + > + if (lwp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT) > { > if (debug_threads) > { > @@ -856,19 +833,16 @@ check_stopped_by_breakpoint (struct lwp_info *lwp) > > /* Back up the PC if necessary. */ > if (pc != sw_breakpoint_pc) > - { > + { > struct regcache *regcache > = get_thread_regcache (current_thread, 1); > (*the_low_target.set_pc) (regcache, sw_breakpoint_pc); > } > > - lwp->stop_pc = sw_breakpoint_pc; > - lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; > - current_thread = saved_thread; > - return 1; > + /* Update this so we record the correct stop PC below. */ > + pc = sw_breakpoint_pc; > } > - > - if (hardware_breakpoint_inserted_here (pc)) > + else if (lwp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT) > { > if (debug_threads) > { > @@ -877,16 +851,31 @@ check_stopped_by_breakpoint (struct lwp_info *lwp) > debug_printf ("CSBB: %s stopped by hardware breakpoint\n", > target_pid_to_str (ptid_of (thr))); > } > + } > + else if (lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT) > + { > + if (debug_threads) > + { > + struct thread_info *thr = get_lwp_thread (lwp); > > - lwp->stop_pc = pc; > - lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; > - current_thread = saved_thread; > - return 1; > + debug_printf ("CSBB: %s stopped by hardware watchpoint\n", > + target_pid_to_str (ptid_of (thr))); > + } > } > -#endif > + else if (lwp->stop_reason == TARGET_STOPPED_BY_SINGLE_STEP) > + { > + if (debug_threads) > + { > + struct thread_info *thr = get_lwp_thread (lwp); > > + debug_printf ("CSBB: %s stopped by trace\n", > + target_pid_to_str (ptid_of (thr))); > + } > + } > + > + lwp->stop_pc = pc; > current_thread = saved_thread; > - return 0; > + return 1; > } > > static struct lwp_info * > @@ -2434,8 +2423,8 @@ linux_low_filter_event (int lwpid, int wstat) > child->syscall_state = TARGET_WAITKIND_IGNORE; > } > > - /* Be careful to not overwrite stop_pc until > - check_stopped_by_breakpoint is called. */ > + /* Be careful to not overwrite stop_pc until save_stop_reason is > + called. */ > if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP > && linux_is_extended_waitstatus (wstat)) > { > @@ -2448,27 +2437,12 @@ linux_low_filter_event (int lwpid, int wstat) > } > } > > - /* Check first whether this was a SW/HW breakpoint before checking > - watchpoints, because at least s390 can't tell the data address of > - hardware watchpoint hits, and returns stopped-by-watchpoint as > - long as there's a watchpoint set. */ > if (WIFSTOPPED (wstat) && linux_wstatus_maybe_breakpoint (wstat)) > { > - if (check_stopped_by_breakpoint (child)) > + if (save_stop_reason (child)) > have_stop_pc = 1; > } > > - /* Note that TRAP_HWBKPT can indicate either a hardware breakpoint > - or hardware watchpoint. Check which is which if we got > - TARGET_STOPPED_BY_HW_BREAKPOINT. Likewise, we may have single > - stepped an instruction that triggered a watchpoint. In that > - case, on some architectures (such as x86), instead of > - TRAP_HWBKPT, si_code indicates TRAP_TRACE, and we need to check > - the debug registers separately. */ > - if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP > - && child->stop_reason != TARGET_STOPPED_BY_SW_BREAKPOINT) > - check_stopped_by_watchpoint (child); > - > if (!have_stop_pc) > child->stop_pc = get_pc (child); > > @@ -3209,7 +3183,7 @@ linux_wait_1 (ptid_t ptid, > hardware single step it means a gdb/gdbserver breakpoint had been > planted on top of a permanent breakpoint, in the case of a software > single step it may just mean that gdbserver hit the reinsert breakpoint. > - The PC has been adjusted by check_stopped_by_breakpoint to point at > + The PC has been adjusted by save_stop_reason to point at > the breakpoint address. > So in the case of the hardware single step advance the PC manually > past the breakpoint and in the case of software single step advance only > diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c > index 6ded38d..0829bcb 100644 > --- a/gdb/linux-nat.c > +++ b/gdb/linux-nat.c > @@ -303,10 +303,11 @@ static struct lwp_info *find_lwp_pid (ptid_t ptid); > > static int lwp_status_pending_p (struct lwp_info *lp); > > -static int check_stopped_by_breakpoint (struct lwp_info *lp); > static int sigtrap_is_event (int status); > static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event; > > +static void save_stop_reason (struct lwp_info *lp); > + > > /* LWP accessors. */ > > @@ -2321,30 +2322,6 @@ check_stopped_by_watchpoint (struct lwp_info *lp) > return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT; > } > > -/* Called when the LWP stopped for a trap that could be explained by a > - watchpoint or a breakpoint. */ > - > -static void > -save_sigtrap (struct lwp_info *lp) > -{ > - gdb_assert (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON); > - gdb_assert (lp->status != 0); > - > - /* Check first if this was a SW/HW breakpoint before checking > - watchpoints, because at least s390 can't tell the data address of > - hardware watchpoint hits, and the kernel returns > - stopped-by-watchpoint as long as there's a watchpoint set. */ > - if (linux_nat_status_is_event (lp->status)) > - check_stopped_by_breakpoint (lp); > - > - /* Note that TRAP_HWBKPT can indicate either a hardware breakpoint > - or hardware watchpoint. Check which is which if we got > - TARGET_STOPPED_BY_HW_BREAKPOINT. */ > - if (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON > - || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT) > - check_stopped_by_watchpoint (lp); > -} > - > /* Returns true if the LWP had stopped for a watchpoint. */ > > static int > @@ -2441,7 +2418,7 @@ stop_wait_callback (struct lwp_info *lp, void *data) > /* Save the sigtrap event. */ > lp->status = status; > gdb_assert (lp->signalled); > - save_sigtrap (lp); > + save_stop_reason (lp); > } > else > { > @@ -2583,29 +2560,32 @@ select_event_lwp_callback (struct lwp_info *lp, void *data) > return 0; > } > > -/* Called when the LWP got a signal/trap that could be explained by a > - software or hardware breakpoint. */ > +/* Called when the LWP stopped for a signal/trap. If it stopped for a > + trap check what caused it (breakpoint, watchpoint, trace, etc.), > + and save the result in the LWP's stop_reason field. If it stopped > + for a breakpoint, decrement the PC if necessary on the lwp's > + architecture. */ > > -static int > -check_stopped_by_breakpoint (struct lwp_info *lp) > +static void > +save_stop_reason (struct lwp_info *lp) > { > - /* Arrange for a breakpoint to be hit again later. We don't keep > - the SIGTRAP status and don't forward the SIGTRAP signal to the > - LWP. We will handle the current event, eventually we will resume > - this LWP, and this breakpoint will trap again. > - > - If we do not do this, then we run the risk that the user will > - delete or disable the breakpoint, but the LWP will have already > - tripped on it. */ > - > - struct regcache *regcache = get_thread_regcache (lp->ptid); > - struct gdbarch *gdbarch = get_regcache_arch (regcache); > + struct regcache *regcache; > + struct gdbarch *gdbarch; > CORE_ADDR pc; > CORE_ADDR sw_bp_pc; > #if USE_SIGTRAP_SIGINFO > siginfo_t siginfo; > #endif > > + gdb_assert (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON); > + gdb_assert (lp->status != 0); > + > + if (!linux_nat_status_is_event (lp->status)) > + return; > + > + regcache = get_thread_regcache (lp->ptid); > + gdbarch = get_regcache_arch (regcache); > + > pc = regcache_read_pc (regcache); > sw_bp_pc = pc - gdbarch_decr_pc_after_break (gdbarch); > > @@ -2614,33 +2594,29 @@ check_stopped_by_breakpoint (struct lwp_info *lp) > { > if (siginfo.si_signo == SIGTRAP) > { > - if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code)) > + if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code) > + && GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code)) > { > - if (debug_linux_nat) > - fprintf_unfiltered (gdb_stdlog, > - "CSBB: %s stopped by software " > - "breakpoint\n", > - target_pid_to_str (lp->ptid)); > - > - /* Back up the PC if necessary. */ > - if (pc != sw_bp_pc) > - regcache_write_pc (regcache, sw_bp_pc); > - > - lp->stop_pc = sw_bp_pc; > + /* The si_code is ambiguous on this arch -- check debug > + registers. */ > + if (!check_stopped_by_watchpoint (lp)) > + lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; > + } > + else if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code)) > + { > + /* If we determine the LWP stopped for a SW breakpoint, > + trust it. Particularly don't check watchpoint > + registers, because at least on s390, we'd find > + stopped-by-watchpoint as long as there's a watchpoint > + set. */ > lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; > - return 1; > } > - else if (siginfo.si_code == TRAP_HWBKPT) > + else if (GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code)) > { > - if (debug_linux_nat) > - fprintf_unfiltered (gdb_stdlog, > - "CSBB: %s stopped by hardware " > - "breakpoint/watchpoint\n", > - target_pid_to_str (lp->ptid)); > - > - lp->stop_pc = pc; > - lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; > - return 1; > + /* This can indicate either a hardware breakpoint or > + hardware watchpoint. Check debug registers. */ > + if (!check_stopped_by_watchpoint (lp)) > + lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; > } > else if (siginfo.si_code == TRAP_TRACE) > { > @@ -2648,6 +2624,13 @@ check_stopped_by_breakpoint (struct lwp_info *lp) > fprintf_unfiltered (gdb_stdlog, > "CSBB: %s stopped by trace\n", > target_pid_to_str (lp->ptid)); > + > + /* We may have single stepped an instruction that > + triggered a watchpoint. In that case, on some > + architectures (such as x86), instead of TRAP_HWBKPT, > + si_code indicates TRAP_TRACE, and we need to check > + the debug registers separately. */ > + check_stopped_by_watchpoint (lp); > } > } > } > @@ -2658,6 +2641,18 @@ check_stopped_by_breakpoint (struct lwp_info *lp) > { > /* The LWP was either continued, or stepped a software > breakpoint instruction. */ > + lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; > + } > + > + if (hardware_breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) > + lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; > + > + if (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON) > + check_stopped_by_watchpoint (lp); > +#endif > + > + if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT) > + { > if (debug_linux_nat) > fprintf_unfiltered (gdb_stdlog, > "CSBB: %s stopped by software breakpoint\n", > @@ -2667,25 +2662,25 @@ check_stopped_by_breakpoint (struct lwp_info *lp) > if (pc != sw_bp_pc) > regcache_write_pc (regcache, sw_bp_pc); > > - lp->stop_pc = sw_bp_pc; > - lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; > - return 1; > + /* Update this so we record the correct stop PC below. */ > + pc = sw_bp_pc; > } > - > - if (hardware_breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) > + else if (lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT) > { > if (debug_linux_nat) > fprintf_unfiltered (gdb_stdlog, > - "CSBB: stopped by hardware breakpoint %s\n", > + "CSBB: %s stopped by hardware breakpoint\n", > + target_pid_to_str (lp->ptid)); > + } > + else if (lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT) > + { > + if (debug_linux_nat) > + fprintf_unfiltered (gdb_stdlog, > + "CSBB: %s stopped by hardware watchpoint\n", > target_pid_to_str (lp->ptid)); > - > - lp->stop_pc = pc; > - lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; > - return 1; > } > -#endif > > - return 0; > + lp->stop_pc = pc; > } > > > @@ -3057,7 +3052,7 @@ linux_nat_filter_event (int lwpid, int status) > /* An interesting event. */ > gdb_assert (lp); > lp->status = status; > - save_sigtrap (lp); > + save_stop_reason (lp); > return lp; > } > > diff --git a/gdb/nat/linux-ptrace.h b/gdb/nat/linux-ptrace.h > index ba58717..1d137e8 100644 > --- a/gdb/nat/linux-ptrace.h > +++ b/gdb/nat/linux-ptrace.h > @@ -119,14 +119,14 @@ struct buffer; > /* The x86 kernel gets some of the si_code values backwards, like > this: > > - | what | si_code | > - |------------------------------------------+------------| > - | software breakpoints (int3) | SI_KERNEL | > - | single-steps | TRAP_TRACE | > - | single-stepping a syscall | TRAP_BRKPT | > - | user sent SIGTRAP | 0 | > - | exec SIGTRAP (when no PTRACE_EVENT_EXEC) | 0 | > - | hardware breakpoints/watchpoints | TRAP_HWBPT | > + | what | si_code | > + |------------------------------------------+-------------| > + | software breakpoints (int3) | SI_KERNEL | > + | single-steps | TRAP_TRACE | > + | single-stepping a syscall | TRAP_BRKPT | > + | user sent SIGTRAP | 0 | > + | exec SIGTRAP (when no PTRACE_EVENT_EXEC) | 0 | > + | hardware breakpoints/watchpoints | TRAP_HWBKPT | > > That is, it reports SI_KERNEL for software breakpoints (and only > for those), and TRAP_BRKPT for single-stepping a syscall... If the > @@ -140,14 +140,32 @@ struct buffer; > in SPU code on a Cell/B.E. However, SI_KERNEL is never seen > on a SIGTRAP for any other reason. > > - The generic Linux target code should use GDB_ARCH_IS_TRAP_BRKPT > - instead of TRAP_BRKPT to abstract out these peculiarities. */ > + The MIPS kernel uses SI_KERNEL for all kernel generated traps. > + Since: > + > + - MIPS doesn't do hardware single-step > + - We don't need to care about exec SIGTRAPs, since we assume > + PTRACE_EVENT_EXEC. > + - The MIPS kernel doesn't support hardware breakpoints. > + > + on MIPS, all we need to care about is distinguishing between > + software breakpoints and hardware watchpoints, which can be done by > + peeking the debug registers. > + > + The generic Linux target code should use GDB_ARCH_IS_TRAP_* instead > + of TRAP_* to abstract out these peculiarities. */ > #if defined __i386__ || defined __x86_64__ > # define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL) > +# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT) > #elif defined __powerpc__ > # define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL || (X) == TRAP_BRKPT) > +# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT) > +#elif defined __mips__ > +# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL) > +# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == SI_KERNEL) > #else > # define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == TRAP_BRKPT) > +# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT) > #endif > > #ifndef TRAP_HWBKPT > I've tried it with a few MIPS/Linux boards and it works fine for hardware watchpoints and software breakpoints again. Thanks, Luis