From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25034 invoked by alias); 30 Jun 2009 10:54:04 -0000 Received: (qmail 25023 invoked by uid 22791); 30 Jun 2009 10:54:03 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_63,SPF_PASS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.45.13) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 30 Jun 2009 10:53:55 +0000 Received: from zps37.corp.google.com (zps37.corp.google.com [172.25.146.37]) by smtp-out.google.com with ESMTP id n5UArru9015252 for ; Tue, 30 Jun 2009 03:53:53 -0700 Received: from localhost (ruffy.mtv.corp.google.com [172.18.118.116]) by zps37.corp.google.com with ESMTP id n5UArp9S030326 for ; Tue, 30 Jun 2009 03:53:51 -0700 Received: by localhost (Postfix, from userid 67641) id 5FBD7846CA; Tue, 30 Jun 2009 03:53:51 -0700 (PDT) To: gdb-patches@sourceware.org Subject: [RFC] add h/w breakpoints to x86-linux gdbserver Message-Id: <20090630105351.5FBD7846CA@localhost> Date: Tue, 30 Jun 2009 10:54:00 -0000 From: dje@google.com (Doug Evans) X-System-Of-Record: true X-IsSubscribed: yes 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 X-SW-Source: 2009-06/txt/msg00860.txt.bz2 Hi. This patch is just an experiment in adding h/w breakpoints to x86-linux gdbserver. It requires this patch: http://sourceware.org/ml/gdb-patches/2009-06/msg00859.html One open issue is that the "exec" target doesn't support h/w breakpoints so "hbreak foo" fails when the program isn't running, but if you get the program running first, then hbreak works. 2009-06-30 Doug Evans Add h/w breakpoints to x86-linux gdbserver. * i386-low.h (i386_low_insert_hw_breakpoint): Declare. (i386_low_remove_hw_breakpoint): Declare. * i386-low.c (i386_low_insert_hw_breakpoint): New function. (i386_low_remove_hw_breakpoint): New function. * linux-x86-low.c (x86_insert_point): Handle h/w breakpoint packets. (x86_remove_point): Ditto. * gdb.base/hbreak.exp: New file. * gdb.base/hbreak.c: New file. --- gdbserver/i386-low.h 2009-06-30 02:09:41.000000000 -0700 +++ gdbserver/i386-low.h 2009-06-30 03:35:55.000000000 -0700 @@ -82,6 +82,16 @@ extern int i386_low_stopped_data_address /* Return true if the inferior has some watchpoint that triggered. Otherwise return false. */ extern int i386_low_stopped_by_watchpoint (struct i386_debug_reg_state *state); + +/* Insert a hardware-assisted breakpoint at ADDR. + Return 0 on success, -1 on failure. */ +extern int i386_low_insert_hw_breakpoint (struct i386_debug_reg_state *state, + CORE_ADDR addr); + +/* Remove a hardware-assisted breakpoint at ADDR. + Return 0 on success, -1 on failure. */ +extern int i386_low_remove_hw_breakpoint (struct i386_debug_reg_state *state, + CORE_ADDR addr); /* Each target needs to provide several low-level functions that will be called to insert watchpoints and hardware breakpoints --- gdbserver/i386-low.c~ 2009-06-30 02:10:04.000000000 -0700 +++ gdbserver/i386-low.c 2009-06-30 01:52:51.000000000 -0700 @@ -575,3 +575,37 @@ i386_low_stopped_by_watchpoint (struct i CORE_ADDR addr = 0; return i386_low_stopped_data_address (state, &addr); } + +/* Support for h/w breakpoints. */ + +/* Insert a hardware-assisted breakpoint at ADDR. + Return 0 on success, -1 on failure. */ + +int +i386_low_insert_hw_breakpoint (struct i386_debug_reg_state *state, + CORE_ADDR addr) +{ + unsigned len_rw = i386_length_and_rw_bits (1, hw_execute); + int retval = i386_insert_aligned_watchpoint (state, addr, len_rw); + + if (debug_hw_points) + i386_show_dr (state, "insert_hwbp", addr, 1, hw_execute); + + return retval; +} + +/* Remove a hardware-assisted breakpoint at ADDR. + Return 0 on success, -1 on failure. */ + +int +i386_low_remove_hw_breakpoint (struct i386_debug_reg_state *state, + CORE_ADDR addr) +{ + unsigned len_rw = i386_length_and_rw_bits (1, hw_execute); + int retval = i386_remove_aligned_watchpoint (state, addr, len_rw); + + if (debug_hw_points) + i386_show_dr (state, "remove_hwbp", addr, 1, hw_execute); + + return retval; +} --- gdbserver/linux-x86-low.c 2009-06-30 02:08:55.000000000 -0700 +++ gdbserver/linux-x86-low.c 2009-06-30 01:50:05.000000000 -0700 @@ -433,6 +433,9 @@ x86_insert_point (char type, CORE_ADDR a struct process_info *proc = current_process (); switch (type) { + case '1': + return i386_low_insert_hw_breakpoint (&proc->private->arch_private->debug_reg_state, + addr); case '2': case '3': case '4': @@ -450,6 +453,9 @@ x86_remove_point (char type, CORE_ADDR a struct process_info *proc = current_process (); switch (type) { + case '1': + return i386_low_remove_hw_breakpoint (&proc->private->arch_private->debug_reg_state, + addr); case '2': case '3': case '4': Index: testsuite/gdb.base/hbreak.c =================================================================== RCS file: testsuite/gdb.base/hbreak.c diff -N testsuite/gdb.base/hbreak.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.base/hbreak.c 30 Jun 2009 10:38:35 -0000 @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +void +break_function (void) +{ +} + +int +main () +{ + break_function (); + return 0; +} Index: testsuite/gdb.base/hbreak.exp =================================================================== RCS file: testsuite/gdb.base/hbreak.exp diff -N testsuite/gdb.base/hbreak.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.base/hbreak.exp 30 Jun 2009 10:38:35 -0000 @@ -0,0 +1,69 @@ +# Copyright 2009 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test hbreak. +# Targets need to add "set_board_info gdb,hardware_breakpoints 1" +# to their board files. + +if $tracelevel { + strace $tracelevel +} + +# Skip if not supported. + +if ![target_info exists gdb,hardware_breakpoints] { + unsupported "hbreak" + return +} + +set testfile "hbreak" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested hbreak.exp + return +} + +if [get_compiler_info ${binfile}] { + return +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load $binfile + +# We can't do hbreaks yet as the "exec" target doesn't support hbreak. +# Once we get the x86 linux child target instantiated, for example, +# then we can do hbreak. So first run to main. +# ??? Arguably broken, not sure how to fix. + +if { ![runto_main] } { + fail "Can't run to main" + return +} + +gdb_test "hbreak break_function" \ + "Hardware assisted breakpoint 2 at .*: file .*${srcfile}, line .*" \ + "breakpoint on break_function" + +gdb_test "continue" \ + ".*Breakpoint 2, break_function ().*" \ + "run to break_function" + +gdb_continue_to_end "hbreak"