diff -ur gdb-7.3.50~cvs20110627-orig/gdb/gnu-nat.c gdb-7.3.50~cvs20110627/gdb/gnu-nat.c --- gdb-7.3.50~cvs20110627-orig/gdb/gnu-nat.c 2011-06-27 23:37:36.000000000 +0000 +++ gdb-7.3.50~cvs20110627/gdb/gnu-nat.c 2011-08-21 23:00:39.000000000 +0000 @@ -989,6 +989,16 @@ 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 diff -ur gdb-7.3.50~cvs20110627-orig/gdb/gnu-nat.h gdb-7.3.50~cvs20110627/gdb/gnu-nat.h --- gdb-7.3.50~cvs20110627-orig/gdb/gnu-nat.h 2011-08-21 23:08:19.000000000 +0000 +++ gdb-7.3.50~cvs20110627/gdb/gnu-nat.h 2011-08-21 23:08:24.000000000 +0000 @@ -30,6 +30,9 @@ /* 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); diff -ur gdb-7.3.50~cvs20110627-orig/gdb/i386gnu-nat.c gdb-7.3.50~cvs20110627/gdb/i386gnu-nat.c --- gdb-7.3.50~cvs20110627-orig/gdb/i386gnu-nat.c 2011-06-27 23:37:36.000000000 +0000 +++ gdb-7.3.50~cvs20110627/gdb/i386gnu-nat.c 2011-08-21 23:33:38.000000000 +0000 @@ -19,6 +19,7 @@ along with this program. If not, see . */ #include "defs.h" +#include "i386-nat.h" #include "inferior.h" #include "floatformat.h" #include "regcache.h" @@ -36,6 +37,7 @@ #include "i386-tdep.h" #include "gnu-nat.h" +#include "inf-child.h" #include "i387-tdep.h" #ifdef HAVE_SYS_PROCFS_H @@ -297,6 +299,142 @@ } } + +/* 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); +} + +/* Set address REGNUM (zero based) to zero in all threads. */ + +static void +i386_gnu_dr_reset_addr (int regnum) +{ + i386_gnu_dr_set_addr (regnum, 0); +} + +/* Get DR_STATUS from only the one thread of INFERIOR_PTID. */ + +static unsigned long +i386_gnu_dr_get_status (void) +{ + struct proc *thread; + struct i386_debug_state regs; + + /* Make sure we know about new threads. */ + inf_update_procs (gnu_current_inf); + + thread = inf_tid_to_thread (gnu_current_inf, + ptid_get_tid (inferior_ptid)); + i386_gnu_dr_get(®s, thread); + + return regs.dr[DR_STATUS]; +} + +/* Unset MASK bits in DR_STATUS in all threads. */ + +static void +i386_gnu_dr_unset_status (unsigned long mask) +{ + void f(struct proc *thread) + { + struct i386_debug_state regs; + i386_gnu_dr_get(®s, thread); + regs.dr[DR_STATUS] &= ~mask; + i386_gnu_dr_set(®s, thread); + } + + inf_update_procs (gnu_current_inf); + inf_threads(gnu_current_inf, f); +} +#endif /* i386_DEBUG_STATE */ + /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_i386gnu_nat; @@ -308,6 +446,17 @@ /* 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.reset_addr = i386_gnu_dr_reset_addr; + i386_dr_low.get_status = i386_gnu_dr_get_status; + i386_dr_low.unset_status = i386_gnu_dr_unset_status; + i386_set_debug_register_length (4); +#endif /* i386_DEBUG_STATE */ + t->to_fetch_registers = gnu_fetch_registers; t->to_store_registers = gnu_store_registers; diff -ur gdb-7.3.50~cvs20110627-orig/gdb/config/i386/i386gnu.mh gdb-7.3.50~cvs20110627-mine/gdb/config/i386/i386gnu.mh --- gdb-7.3.50~cvs20110627-orig/gdb/config/i386/i386gnu.mh 2011-06-27 23:37:36.000000000 +0000 +++ gdb-7.3.50~cvs20110627-mine/gdb/config/i386/i386gnu.mh 2011-08-21 22:31:02.000000000 +0000 @@ -1,5 +1,5 @@ # Host: Intel 386 running the GNU Hurd -NATDEPFILES= i386gnu-nat.o gnu-nat.o corelow.o core-regset.o fork-child.o \ +NATDEPFILES= i386gnu-nat.o gnu-nat.o i386-nat.o corelow.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