mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-03 04:12:10 +08:00
Add hardware watchpoint support for x86 GNU Hurd.
gdb/ * config/i386/i386gnu.mh (NATDEPFILES): Add x86-nat.o and x86-dregs.o. * gnu-nat.c (inf_threads): New function. * gnu-nat.h (inf_threads_ftype): New typedef. (inf_threads): New declaration. * i386gnu-nat.c: Include "x86-nat.h" and "inf-child.h". [i386_DEBUG_STATE] (i386_gnu_dr_get, i386_gnu_dr_set) (i386_gnu_dr_set_control_one, i386_gnu_dr_set_control) (i386_gnu_dr_set_addr_one, 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. (reg_addr): New structure. (_initialize_i386gnu_nat) [i386_DEBUG_STATE]: Initialize hardware i386 debugging register hooks. * NEWS: Mention this.
This commit is contained in:
parent
70e99720f9
commit
05db5edd79
@ -1,3 +1,21 @@
|
||||
2014-09-16 Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
|
||||
* config/i386/i386gnu.mh (NATDEPFILES): Add x86-nat.o and
|
||||
x86-dregs.o.
|
||||
* gnu-nat.c (inf_threads): New function.
|
||||
* gnu-nat.h (inf_threads_ftype): New typedef.
|
||||
(inf_threads): New declaration.
|
||||
* i386gnu-nat.c: Include "x86-nat.h" and "inf-child.h".
|
||||
[i386_DEBUG_STATE] (i386_gnu_dr_get, i386_gnu_dr_set)
|
||||
(i386_gnu_dr_set_control_one, i386_gnu_dr_set_control)
|
||||
(i386_gnu_dr_set_addr_one, 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.
|
||||
(reg_addr): New structure.
|
||||
(_initialize_i386gnu_nat) [i386_DEBUG_STATE]: Initialize hardware
|
||||
i386 debugging register hooks.
|
||||
* NEWS: Mention this.
|
||||
|
||||
2014-08-13 Omair Javaid <omair.javaid@linaro.org>
|
||||
|
||||
* arm-tdep.c (arm_record_vdata_transfer_insn): Added record handler for
|
||||
|
2
gdb/NEWS
2
gdb/NEWS
@ -3,6 +3,8 @@
|
||||
|
||||
*** Changes since GDB 7.8
|
||||
|
||||
* GDB now supports hardware watchpoints on x86 GNU Hurd.
|
||||
|
||||
* Python Scripting
|
||||
You can now access frame registers from Python scripts.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
# 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 \
|
||||
x86-nat.o x86-dregs.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
|
||||
|
@ -983,6 +983,17 @@ inf_port_to_thread (struct inf *inf, mach_port_t port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See gnu-nat.h. */
|
||||
|
||||
void
|
||||
inf_threads (struct inf *inf, inf_threads_ftype *f, void *arg)
|
||||
{
|
||||
struct proc *thread;
|
||||
|
||||
for (thread = inf->threads; thread; thread = thread->next)
|
||||
f (thread, arg);
|
||||
}
|
||||
|
||||
|
||||
/* Make INF's list of threads be consistent with reality of TASK. */
|
||||
void
|
||||
|
@ -29,6 +29,11 @@ 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);
|
||||
|
||||
typedef void (inf_threads_ftype) (struct proc *thread, void *arg);
|
||||
|
||||
/* Call F for every thread in inferior INF, passing ARG as second parameter. */
|
||||
void inf_threads (struct inf *inf, inf_threads_ftype *f, void *arg);
|
||||
|
||||
/* Makes sure that INF's thread list is synced with the actual process. */
|
||||
int inf_update_procs (struct inf *inf);
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "x86-nat.h"
|
||||
#include "inferior.h"
|
||||
#include "floatformat.h"
|
||||
#include "regcache.h"
|
||||
@ -30,6 +31,7 @@
|
||||
#include "i386-tdep.h"
|
||||
|
||||
#include "gnu-nat.h"
|
||||
#include "inf-child.h"
|
||||
#include "i387-tdep.h"
|
||||
|
||||
#ifdef HAVE_SYS_PROCFS_H
|
||||
@ -304,6 +306,142 @@ gnu_store_registers (struct target_ops *ops,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Support for debug registers. */
|
||||
|
||||
#ifdef i386_DEBUG_STATE
|
||||
/* 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 != 0 || count != i386_DEBUG_STATE_COUNT)
|
||||
warning (_("Couldn't fetch debug state from %s"),
|
||||
proc_string (thread));
|
||||
}
|
||||
|
||||
/* 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 != 0)
|
||||
warning (_("Couldn't store debug state into %s"),
|
||||
proc_string (thread));
|
||||
}
|
||||
|
||||
/* Set DR_CONTROL in THREAD. */
|
||||
|
||||
static void
|
||||
i386_gnu_dr_set_control_one (struct proc *thread, void *arg)
|
||||
{
|
||||
unsigned long *control = arg;
|
||||
struct i386_debug_state regs;
|
||||
|
||||
i386_gnu_dr_get (®s, thread);
|
||||
regs.dr[DR_CONTROL] = *control;
|
||||
i386_gnu_dr_set (®s, thread);
|
||||
}
|
||||
|
||||
/* Set DR_CONTROL to CONTROL in all threads. */
|
||||
|
||||
static void
|
||||
i386_gnu_dr_set_control (unsigned long control)
|
||||
{
|
||||
inf_update_procs (gnu_current_inf);
|
||||
inf_threads (gnu_current_inf, i386_gnu_dr_set_control_one, &control);
|
||||
}
|
||||
|
||||
/* Parameters to set a debugging address. */
|
||||
|
||||
struct reg_addr
|
||||
{
|
||||
int regnum; /* Register number (zero based). */
|
||||
CORE_ADDR addr; /* Address. */
|
||||
};
|
||||
|
||||
/* Set address REGNUM (zero based) to ADDR in THREAD. */
|
||||
|
||||
static void
|
||||
i386_gnu_dr_set_addr_one (struct proc *thread, void *arg)
|
||||
{
|
||||
struct reg_addr *reg_addr = arg;
|
||||
struct i386_debug_state regs;
|
||||
|
||||
i386_gnu_dr_get (®s, thread);
|
||||
regs.dr[reg_addr->regnum] = reg_addr->addr;
|
||||
i386_gnu_dr_set (®s, thread);
|
||||
}
|
||||
|
||||
/* Set address REGNUM (zero based) to ADDR in all threads. */
|
||||
|
||||
static void
|
||||
i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr)
|
||||
{
|
||||
struct reg_addr reg_addr;
|
||||
|
||||
gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
|
||||
|
||||
reg_addr.regnum = regnum;
|
||||
reg_addr.addr = addr;
|
||||
|
||||
inf_update_procs (gnu_current_inf);
|
||||
inf_threads (gnu_current_inf, i386_gnu_dr_set_addr_one, ®_addr);
|
||||
}
|
||||
|
||||
/* 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 (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
|
||||
|
||||
return i386_gnu_dr_get_reg (inferior_ptid, 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;
|
||||
|
||||
@ -315,6 +453,18 @@ _initialize_i386gnu_nat (void)
|
||||
/* Fill in the generic GNU/Hurd methods. */
|
||||
t = gnu_target ();
|
||||
|
||||
#ifdef i386_DEBUG_STATE
|
||||
x86_use_watchpoints (t);
|
||||
|
||||
x86_dr_low.set_control = i386_gnu_dr_set_control;
|
||||
gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT);
|
||||
x86_dr_low.set_addr = i386_gnu_dr_set_addr;
|
||||
x86_dr_low.get_addr = i386_gnu_dr_get_addr;
|
||||
x86_dr_low.get_status = i386_gnu_dr_get_status;
|
||||
x86_dr_low.get_control = i386_gnu_dr_get_control;
|
||||
x86_set_debug_register_length (4);
|
||||
#endif /* i386_DEBUG_STATE */
|
||||
|
||||
t->to_fetch_registers = gnu_fetch_registers;
|
||||
t->to_store_registers = gnu_store_registers;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user