From patchwork Sun Aug 31 01:57:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 2602 Received: (qmail 26641 invoked by alias); 31 Aug 2014 02:01:43 -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 22860 invoked by uid 89); 31 Aug 2014 02:01:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.4 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, UNWANTED_LANGUAGE_BODY autolearn=ham version=3.3.2 X-HELO: sonata.ens-lyon.org Received: from sonata.ens-lyon.org (HELO sonata.ens-lyon.org) (140.77.166.138) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sun, 31 Aug 2014 02:00:57 +0000 Received: from localhost (localhost [127.0.0.1]) by sonata.ens-lyon.org (Postfix) with ESMTP id 54CAD20092 for ; Sun, 31 Aug 2014 04:00:53 +0200 (CEST) Received: from sonata.ens-lyon.org ([127.0.0.1]) by localhost (sonata.ens-lyon.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vyz55Mq9NQrJ for ; Sun, 31 Aug 2014 04:00:53 +0200 (CEST) Received: from type.youpi.perso.aquilenet.fr (youpi.perso.aquilenet.fr [80.67.176.89]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sonata.ens-lyon.org (Postfix) with ESMTPSA id D800220090 for ; Sun, 31 Aug 2014 04:00:52 +0200 (CEST) Received: from samy by type.youpi.perso.aquilenet.fr with local (Exim 4.84) (envelope-from ) id 1XNuRn-0006wD-VU for gdb-patches@sourceware.org; Sun, 31 Aug 2014 04:00:51 +0200 Resent-From: Samuel Thibault Resent-Date: Sun, 31 Aug 2014 04:00:51 +0200 Resent-Message-ID: <20140831020051.GP19374@type.youpi.perso.aquilenet.fr> Resent-To: gdb-patches@sourceware.org Date: Sun, 31 Aug 2014 03:57:27 +0200 From: Samuel Thibault To: gdb-patches@gnu.org Cc: thomas@codesourcery.com, bug-hurd@gnu.org Subject: [PATCH,Hurd] Add hardware watch support Message-ID: <20140831015727.GH19374@type.youpi.perso.aquilenet.fr> Mail-Followup-To: gdb-patches@gnu.org, thomas@codesourcery.com, bug-hurd@gnu.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21+34 (58baf7c9f32f) (2010-12-30) 2014-08-31 Samuel Thibault Add hardware watch support to gnu-i386 platform. * gdb/gdb/gnu-nat.c (inf_threads): New function. * gdb/gdb/gnu-nat.h (inf_threads): New declaration. * gdb/gdb/i386gnu-nat.c: Include "i386-nat.h" and "inf-child.h" [i386_DEBUG_STATE] (DR_FIRSTADDR, DR_LASTADDR, DR_STATUS, DR_CONTROL): New macros [i386_DEBUG_STATE] (i386_gnu_dr_get, i386_gnu_dr_set, i386_gnu_dr_set_control, i386_gnu_dr_set_addr, i386_gnu_dr_get_reg, i386_gnu_dr_get_addr, 386_gnu_dr_get_status, i386_gnu_dr_get_control): New functions [i386_DEBUG_STATE] (_initialize_i386gnu_nat): Initialize hardware i386 debugging register hooks. Index: gdb/gdb/gnu-nat.c =================================================================== --- gdb.orig/gdb/gnu-nat.c +++ gdb/gdb/gnu-nat.c @@ -987,6 +987,16 @@ inf_port_to_thread (struct inf *inf, mac return 0; } +/* Interate F over threads. */ +void +inf_threads (struct inf *inf, void (*f)(struct proc *thread)) +{ + struct proc *thread; + + for (thread = inf->threads; thread; thread = thread->next) + f(thread); +} + /* Make INF's list of threads be consistent with reality of TASK. */ void Index: gdb/gdb/gnu-nat.h =================================================================== --- gdb.orig/gdb/gnu-nat.h +++ gdb/gdb/gnu-nat.h @@ -29,6 +29,9 @@ extern struct inf *gnu_current_inf; /* Converts a GDB pid to a struct proc. */ struct proc *inf_tid_to_thread (struct inf *inf, int tid); +/* Iterate F over threads */ +void inf_threads (struct inf *inf, void (*f)(struct proc *thread)); + /* Makes sure that INF's thread list is synced with the actual process. */ int inf_update_procs (struct inf *inf); Index: gdb/gdb/i386gnu-nat.c =================================================================== --- gdb.orig/gdb/i386gnu-nat.c +++ gdb/gdb/i386gnu-nat.c @@ -18,6 +18,7 @@ along with this program. If not, see . */ #include "defs.h" +#include "i386-nat.h" #include "inferior.h" #include "floatformat.h" #include "regcache.h" @@ -35,6 +36,7 @@ #include "i386-tdep.h" #include "gnu-nat.h" +#include "inf-child.h" #include "i387-tdep.h" #ifdef HAVE_SYS_PROCFS_H @@ -309,6 +311,142 @@ gnu_store_registers (struct target_ops * } } + +/* Support for debug registers. */ + +#ifdef i386_DEBUG_STATE + +#ifndef DR_FIRSTADDR +#define DR_FIRSTADDR 0 +#endif + +#ifndef DR_LASTADDR +#define DR_LASTADDR 3 +#endif + +#ifndef DR_STATUS +#define DR_STATUS 6 +#endif + +#ifndef DR_CONTROL +#define DR_CONTROL 7 +#endif + +/* Get debug registers for thread THREAD. */ + +static void +i386_gnu_dr_get(struct i386_debug_state *regs, struct proc *thread) +{ + mach_msg_type_number_t count = i386_DEBUG_STATE_COUNT; + error_t err; + + err = thread_get_state (thread->port, i386_DEBUG_STATE, + (thread_state_t) regs, &count); + if (err || count != i386_DEBUG_STATE_COUNT) + { + warning (_("Couldn't fetch debug state from %s"), + proc_string (thread)); + return; + } +} + +/* Set debug registers for thread THREAD. */ + +static void +i386_gnu_dr_set(const struct i386_debug_state *regs, struct proc *thread) +{ + error_t err; + + err = thread_set_state (thread->port, i386_DEBUG_STATE, + (thread_state_t) regs, i386_DEBUG_STATE_COUNT); + if (err) + { + warning (_("Couldn't store debug state into %s"), + proc_string (thread)); + return; + } +} + +/* Set DR_CONTROL to ADDR in all threads. */ + +static void +i386_gnu_dr_set_control (unsigned long control) +{ + void f(struct proc *thread) + { + struct i386_debug_state regs; + i386_gnu_dr_get(®s, thread); + regs.dr[DR_CONTROL] = control; + i386_gnu_dr_set(®s, thread); + } + + inf_update_procs (gnu_current_inf); + inf_threads(gnu_current_inf, f); +} + +/* Set address REGNUM (zero based) to ADDR in all threads. */ + +static void +i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr) +{ + void f(struct proc *thread) + { + struct i386_debug_state regs; + i386_gnu_dr_get(®s, thread); + regs.dr[DR_FIRSTADDR + regnum] = addr; + i386_gnu_dr_set(®s, thread); + } + + gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); + + inf_update_procs (gnu_current_inf); + inf_threads(gnu_current_inf, f); +} + +/* Get debug register REGNUM value from only the one LWP of PTID. */ + +static unsigned long +i386_gnu_dr_get_reg (ptid_t ptid, int regnum) +{ + struct i386_debug_state regs; + struct proc *thread; + + /* Make sure we know about new threads. */ + inf_update_procs (gnu_current_inf); + + thread = inf_tid_to_thread (gnu_current_inf, ptid_get_lwp (ptid)); + i386_gnu_dr_get(®s, thread); + + return regs.dr[regnum]; +} + +/* Return the inferior's debug register REGNUM. */ + +static CORE_ADDR +i386_gnu_dr_get_addr (int regnum) +{ + gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); + + return i386_gnu_dr_get_reg (inferior_ptid, DR_FIRSTADDR + regnum); +} + +/* Get DR_STATUS from only the one thread of INFERIOR_PTID. */ + +static unsigned long +i386_gnu_dr_get_status (void) +{ + return i386_gnu_dr_get_reg (inferior_ptid, DR_STATUS); +} + +/* Return the inferior's DR7 debug control register. */ + +static unsigned long +i386_gnu_dr_get_control (void) +{ + return i386_gnu_dr_get_reg (inferior_ptid, DR_CONTROL); +} +#endif /* i386_DEBUG_STATE */ + /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_i386gnu_nat; @@ -320,6 +458,17 @@ _initialize_i386gnu_nat (void) /* Fill in the generic GNU/Hurd methods. */ t = gnu_target (); +#ifdef i386_DEBUG_STATE + i386_use_watchpoints (t); + + i386_dr_low.set_control = i386_gnu_dr_set_control; + i386_dr_low.set_addr = i386_gnu_dr_set_addr; + i386_dr_low.get_addr = i386_gnu_dr_get_addr; + i386_dr_low.get_status = i386_gnu_dr_get_status; + i386_dr_low.get_control = i386_gnu_dr_get_control; + i386_set_debug_register_length (4); +#endif /* i386_DEBUG_STATE */ + t->to_fetch_registers = gnu_fetch_registers; t->to_store_registers = gnu_store_registers; Index: gdb/gdb/config/i386/i386gnu.mh =================================================================== --- gdb.orig/gdb/config/i386/i386gnu.mh +++ gdb/gdb/config/i386/i386gnu.mh @@ -1,5 +1,5 @@ # Host: Intel 386 running the GNU Hurd -NATDEPFILES= i386gnu-nat.o gnu-nat.o core-regset.o fork-child.o \ +NATDEPFILES= i386gnu-nat.o gnu-nat.o i386-nat.o core-regset.o fork-child.o \ notify_S.o process_reply_S.o msg_reply_S.o \ msg_U.o exc_request_U.o exc_request_S.o HAVE_NATIVE_GCORE_HOST = 1