PR threads/10729
* linux-x86-low.c (update_debug_registers_callback): New. (i386_dr_low_set_addr): Use it. (i386_dr_low_get_addr): New. (i386_dr_low_set_control): Use update_debug_registers_callback. (i386_dr_low_get_control): New. (i386_dr_low_get_status): Adjust. * linux-low.c (linux_stop_lwp): New. * linux-low.h (linux_stop_lwp): Declare. * i386-low.c (I386_DR_GET_RW_LEN): Take the dr7 contents as argument instead of a i386_debug_reg_state. (I386_DR_WATCH_HIT): Take the dr6 contents as argument instead of a i386_debug_reg_state. (i386_insert_aligned_watchpoint): Adjust. (i386_remove_aligned_watchpoint): Adjust. (i386_low_stopped_data_address): Read the debug registers from the inferior instead of from the mirrors. * i386-low.h (struct i386_debug_reg_state): Extend comment. (i386_dr_low_get_addr): Declare. (i386_dr_low_get_control): Declare. (i386_dr_low_get_status): Change prototype. * win32-i386-low.c (dr_status_mirror, dr_control_mirror): New globals. (i386_dr_low_get_addr): New. (i386_dr_low_get_control): New. (i386_dr_low_get_status): Adjust prototype. Return dr_status_mirror. (i386_initial_stuff): Clear dr_status_mirror and dr_control_mirror. (i386_get_thread_context): Adjust. (i386_set_thread_context): Adjust. (i386_thread_added): Adjust.
This commit is contained in:
parent
4563a86028
commit
964e4306f8
|
@ -1,3 +1,40 @@
|
||||||
|
2010-08-25 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
|
PR threads/10729
|
||||||
|
|
||||||
|
* linux-x86-low.c (update_debug_registers_callback): New.
|
||||||
|
(i386_dr_low_set_addr): Use it.
|
||||||
|
(i386_dr_low_get_addr): New.
|
||||||
|
(i386_dr_low_set_control): Use update_debug_registers_callback.
|
||||||
|
(i386_dr_low_get_control): New.
|
||||||
|
(i386_dr_low_get_status): Adjust.
|
||||||
|
* linux-low.c (linux_stop_lwp): New.
|
||||||
|
* linux-low.h (linux_stop_lwp): Declare.
|
||||||
|
|
||||||
|
* i386-low.c (I386_DR_GET_RW_LEN): Take the dr7 contents as
|
||||||
|
argument instead of a i386_debug_reg_state.
|
||||||
|
(I386_DR_WATCH_HIT): Take the dr6 contents as argument instead of
|
||||||
|
a i386_debug_reg_state.
|
||||||
|
(i386_insert_aligned_watchpoint): Adjust.
|
||||||
|
(i386_remove_aligned_watchpoint): Adjust.
|
||||||
|
(i386_low_stopped_data_address): Read the debug registers from the
|
||||||
|
inferior instead of from the mirrors.
|
||||||
|
* i386-low.h (struct i386_debug_reg_state): Extend comment.
|
||||||
|
(i386_dr_low_get_addr): Declare.
|
||||||
|
(i386_dr_low_get_control): Declare.
|
||||||
|
(i386_dr_low_get_status): Change prototype.
|
||||||
|
|
||||||
|
* win32-i386-low.c (dr_status_mirror, dr_control_mirror): New globals.
|
||||||
|
(i386_dr_low_get_addr): New.
|
||||||
|
(i386_dr_low_get_control): New.
|
||||||
|
(i386_dr_low_get_status): Adjust prototype. Return
|
||||||
|
dr_status_mirror.
|
||||||
|
(i386_initial_stuff): Clear dr_status_mirror and
|
||||||
|
dr_control_mirror.
|
||||||
|
(i386_get_thread_context): Adjust.
|
||||||
|
(i386_set_thread_context): Adjust.
|
||||||
|
(i386_thread_added): Adjust.
|
||||||
|
|
||||||
2010-08-24 Pedro Alves <pedro@codesourcery.com>
|
2010-08-24 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
* linux-low.h (linux_thread_area): Delete declaration.
|
* linux-low.h (linux_thread_area): Delete declaration.
|
||||||
|
|
|
@ -132,12 +132,12 @@ enum target_hw_bp_type
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* Get from DR7 the RW and LEN fields for the I'th debug register. */
|
/* Get from DR7 the RW and LEN fields for the I'th debug register. */
|
||||||
#define I386_DR_GET_RW_LEN(state, i) \
|
#define I386_DR_GET_RW_LEN(dr7, i) \
|
||||||
(((state)->dr_control_mirror \
|
(((dr7) \
|
||||||
>> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f)
|
>> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f)
|
||||||
|
|
||||||
/* Did the watchpoint whose address is in the I'th register break? */
|
/* Did the watchpoint whose address is in the I'th register break? */
|
||||||
#define I386_DR_WATCH_HIT(state,i) ((state)->dr_status_mirror & (1 << (i)))
|
#define I386_DR_WATCH_HIT(dr6, i) ((dr6) & (1 << (i)))
|
||||||
|
|
||||||
/* A macro to loop over all debug registers. */
|
/* A macro to loop over all debug registers. */
|
||||||
#define ALL_DEBUG_REGISTERS(i) for (i = 0; i < DR_NADDR; i++)
|
#define ALL_DEBUG_REGISTERS(i) for (i = 0; i < DR_NADDR; i++)
|
||||||
|
@ -271,7 +271,7 @@ i386_insert_aligned_watchpoint (struct i386_debug_reg_state *state,
|
||||||
{
|
{
|
||||||
if (!I386_DR_VACANT (state, i)
|
if (!I386_DR_VACANT (state, i)
|
||||||
&& state->dr_mirror[i] == addr
|
&& state->dr_mirror[i] == addr
|
||||||
&& I386_DR_GET_RW_LEN (state, i) == len_rw_bits)
|
&& I386_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits)
|
||||||
{
|
{
|
||||||
state->dr_ref_count[i]++;
|
state->dr_ref_count[i]++;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -329,7 +329,7 @@ i386_remove_aligned_watchpoint (struct i386_debug_reg_state *state,
|
||||||
{
|
{
|
||||||
if (!I386_DR_VACANT (state, i)
|
if (!I386_DR_VACANT (state, i)
|
||||||
&& state->dr_mirror[i] == addr
|
&& state->dr_mirror[i] == addr
|
||||||
&& I386_DR_GET_RW_LEN (state, i) == len_rw_bits)
|
&& I386_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits)
|
||||||
{
|
{
|
||||||
if (--state->dr_ref_count[i] == 0) /* No longer in use? */
|
if (--state->dr_ref_count[i] == 0) /* No longer in use? */
|
||||||
{
|
{
|
||||||
|
@ -539,21 +539,26 @@ i386_low_stopped_data_address (struct i386_debug_reg_state *state,
|
||||||
CORE_ADDR addr = 0;
|
CORE_ADDR addr = 0;
|
||||||
int i;
|
int i;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
unsigned status;
|
||||||
|
unsigned control;
|
||||||
|
|
||||||
/* Get dr_status_mirror for use by I386_DR_WATCH_HIT. */
|
/* Get the current values the inferior has. If the thread was
|
||||||
i386_dr_low_get_status (state);
|
running when we last changed watchpoints, the mirror no longer
|
||||||
|
represents what was set in this LWP's debug registers. */
|
||||||
|
status = i386_dr_low_get_status ();
|
||||||
|
control = i386_dr_low_get_control ();
|
||||||
|
|
||||||
ALL_DEBUG_REGISTERS (i)
|
ALL_DEBUG_REGISTERS (i)
|
||||||
{
|
{
|
||||||
if (I386_DR_WATCH_HIT (state, i)
|
if (I386_DR_WATCH_HIT (status, i)
|
||||||
/* This second condition makes sure DRi is set up for a data
|
/* This second condition makes sure DRi is set up for a data
|
||||||
watchpoint, not a hardware breakpoint. The reason is
|
watchpoint, not a hardware breakpoint. The reason is
|
||||||
that GDB doesn't call the target_stopped_data_address
|
that GDB doesn't call the target_stopped_data_address
|
||||||
method except for data watchpoints. In other words, I'm
|
method except for data watchpoints. In other words, I'm
|
||||||
being paranoiac. */
|
being paranoiac. */
|
||||||
&& I386_DR_GET_RW_LEN (state, i) != 0)
|
&& I386_DR_GET_RW_LEN (control, i) != 0)
|
||||||
{
|
{
|
||||||
addr = state->dr_mirror[i];
|
addr = i386_dr_low_get_addr (i);
|
||||||
rc = 1;
|
rc = 1;
|
||||||
if (debug_hw_points)
|
if (debug_hw_points)
|
||||||
i386_show_dr (state, "watchpoint_hit", addr, -1, hw_write);
|
i386_show_dr (state, "watchpoint_hit", addr, -1, hw_write);
|
||||||
|
|
|
@ -42,7 +42,10 @@
|
||||||
struct i386_debug_reg_state
|
struct i386_debug_reg_state
|
||||||
{
|
{
|
||||||
/* Mirror the inferior's DRi registers. We keep the status and
|
/* Mirror the inferior's DRi registers. We keep the status and
|
||||||
control registers separated because they don't hold addresses. */
|
control registers separated because they don't hold addresses.
|
||||||
|
Note that since we can change these mirrors while threads are
|
||||||
|
running, we never trust them to explain a cause of a trap.
|
||||||
|
For that, we need to peek directly in the inferior registers. */
|
||||||
CORE_ADDR dr_mirror[DR_NADDR];
|
CORE_ADDR dr_mirror[DR_NADDR];
|
||||||
unsigned dr_status_mirror, dr_control_mirror;
|
unsigned dr_status_mirror, dr_control_mirror;
|
||||||
|
|
||||||
|
@ -100,9 +103,14 @@ extern int i386_low_stopped_by_watchpoint (struct i386_debug_reg_state *state);
|
||||||
extern void i386_dr_low_set_addr (const struct i386_debug_reg_state *state,
|
extern void i386_dr_low_set_addr (const struct i386_debug_reg_state *state,
|
||||||
int regnum);
|
int regnum);
|
||||||
|
|
||||||
|
/* Return the inferior's debug register REGNUM. */
|
||||||
|
extern CORE_ADDR i386_dr_low_get_addr (int regnum);
|
||||||
|
|
||||||
/* Update the inferior's DR7 debug control register from STATE. */
|
/* Update the inferior's DR7 debug control register from STATE. */
|
||||||
extern void i386_dr_low_set_control (const struct i386_debug_reg_state *state);
|
extern void i386_dr_low_set_control (const struct i386_debug_reg_state *state);
|
||||||
|
|
||||||
/* Get the value of the inferior's DR6 debug status register
|
/* Return the value of the inferior's DR7 debug control register. */
|
||||||
and record it in STATE. */
|
extern unsigned i386_dr_low_get_control (void);
|
||||||
extern void i386_dr_low_get_status (struct i386_debug_reg_state *state);
|
|
||||||
|
/* Return the value of the inferior's DR6 debug status register. */
|
||||||
|
extern unsigned i386_dr_low_get_status (void);
|
||||||
|
|
|
@ -2478,6 +2478,12 @@ kill_lwp (unsigned long lwpid, int signo)
|
||||||
return kill (lwpid, signo);
|
return kill (lwpid, signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
linux_stop_lwp (struct lwp_info *lwp)
|
||||||
|
{
|
||||||
|
send_sigstop (lwp);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_sigstop (struct lwp_info *lwp)
|
send_sigstop (struct lwp_info *lwp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -259,6 +259,7 @@ int elf_64_file_p (const char *file);
|
||||||
|
|
||||||
void linux_attach_lwp (unsigned long pid);
|
void linux_attach_lwp (unsigned long pid);
|
||||||
struct lwp_info *find_lwp_pid (ptid_t ptid);
|
struct lwp_info *find_lwp_pid (ptid_t ptid);
|
||||||
|
void linux_stop_lwp (struct lwp_info *lwp);
|
||||||
|
|
||||||
/* From thread-db.c */
|
/* From thread-db.c */
|
||||||
int thread_db_init (int use_events);
|
int thread_db_init (int use_events);
|
||||||
|
|
|
@ -461,30 +461,55 @@ x86_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
|
||||||
error ("Couldn't write debug register");
|
error ("Couldn't write debug register");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
update_debug_registers_callback (struct inferior_list_entry *entry,
|
||||||
|
void *pid_p)
|
||||||
|
{
|
||||||
|
struct lwp_info *lwp = (struct lwp_info *) entry;
|
||||||
|
int pid = *(int *) pid_p;
|
||||||
|
|
||||||
|
/* Only update the threads of this process. */
|
||||||
|
if (pid_of (lwp) == pid)
|
||||||
|
{
|
||||||
|
/* The actual update is done later just before resuming the lwp,
|
||||||
|
we just mark that the registers need updating. */
|
||||||
|
lwp->arch_private->debug_registers_changed = 1;
|
||||||
|
|
||||||
|
/* If the lwp isn't stopped, force it to momentarily pause, so
|
||||||
|
we can update its debug registers. */
|
||||||
|
if (!lwp->stopped)
|
||||||
|
linux_stop_lwp (lwp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the inferior's debug register REGNUM from STATE. */
|
/* Update the inferior's debug register REGNUM from STATE. */
|
||||||
|
|
||||||
void
|
void
|
||||||
i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
|
i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
|
||||||
{
|
{
|
||||||
struct inferior_list_entry *lp;
|
/* Only update the threads of this process. */
|
||||||
CORE_ADDR addr;
|
|
||||||
/* Only need to update the threads of this process. */
|
|
||||||
int pid = pid_of (get_thread_lwp (current_inferior));
|
int pid = pid_of (get_thread_lwp (current_inferior));
|
||||||
|
|
||||||
if (! (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR))
|
if (! (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR))
|
||||||
fatal ("Invalid debug register %d", regnum);
|
fatal ("Invalid debug register %d", regnum);
|
||||||
|
|
||||||
addr = state->dr_mirror[regnum];
|
find_inferior (&all_lwps, update_debug_registers_callback, &pid);
|
||||||
|
}
|
||||||
|
|
||||||
for (lp = all_lwps.head; lp; lp = lp->next)
|
/* Return the inferior's debug register REGNUM. */
|
||||||
{
|
|
||||||
struct lwp_info *lwp = (struct lwp_info *) lp;
|
|
||||||
|
|
||||||
/* The actual update is done later, we just mark that the register
|
CORE_ADDR
|
||||||
needs updating. */
|
i386_dr_low_get_addr (int regnum)
|
||||||
if (pid_of (lwp) == pid)
|
{
|
||||||
lwp->arch_private->debug_registers_changed = 1;
|
struct lwp_info *lwp = get_thread_lwp (current_inferior);
|
||||||
}
|
ptid_t ptid = ptid_of (lwp);
|
||||||
|
|
||||||
|
/* DR6 and DR7 are retrieved with some other way. */
|
||||||
|
gdb_assert (DR_FIRSTADDR <= regnum && regnum < DR_LASTADDR);
|
||||||
|
|
||||||
|
return x86_linux_dr_get (ptid, regnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the inferior's DR7 debug control register from STATE. */
|
/* Update the inferior's DR7 debug control register from STATE. */
|
||||||
|
@ -492,31 +517,33 @@ i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
|
||||||
void
|
void
|
||||||
i386_dr_low_set_control (const struct i386_debug_reg_state *state)
|
i386_dr_low_set_control (const struct i386_debug_reg_state *state)
|
||||||
{
|
{
|
||||||
struct inferior_list_entry *lp;
|
/* Only update the threads of this process. */
|
||||||
/* Only need to update the threads of this process. */
|
|
||||||
int pid = pid_of (get_thread_lwp (current_inferior));
|
int pid = pid_of (get_thread_lwp (current_inferior));
|
||||||
|
|
||||||
for (lp = all_lwps.head; lp; lp = lp->next)
|
find_inferior (&all_lwps, update_debug_registers_callback, &pid);
|
||||||
{
|
}
|
||||||
struct lwp_info *lwp = (struct lwp_info *) lp;
|
|
||||||
|
|
||||||
/* The actual update is done later, we just mark that the register
|
/* Return the inferior's DR7 debug control register. */
|
||||||
needs updating. */
|
|
||||||
if (pid_of (lwp) == pid)
|
unsigned
|
||||||
lwp->arch_private->debug_registers_changed = 1;
|
i386_dr_low_get_control (void)
|
||||||
}
|
{
|
||||||
|
struct lwp_info *lwp = get_thread_lwp (current_inferior);
|
||||||
|
ptid_t ptid = ptid_of (lwp);
|
||||||
|
|
||||||
|
return x86_linux_dr_get (ptid, DR_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the value of the DR6 debug status register from the inferior
|
/* Get the value of the DR6 debug status register from the inferior
|
||||||
and record it in STATE. */
|
and record it in STATE. */
|
||||||
|
|
||||||
void
|
unsigned
|
||||||
i386_dr_low_get_status (struct i386_debug_reg_state *state)
|
i386_dr_low_get_status (void)
|
||||||
{
|
{
|
||||||
struct lwp_info *lwp = get_thread_lwp (current_inferior);
|
struct lwp_info *lwp = get_thread_lwp (current_inferior);
|
||||||
ptid_t ptid = ptid_of (lwp);
|
ptid_t ptid = ptid_of (lwp);
|
||||||
|
|
||||||
state->dr_status_mirror = x86_linux_dr_get (ptid, DR_STATUS);
|
return x86_linux_dr_get (ptid, DR_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Watchpoint support. */
|
/* Watchpoint support. */
|
||||||
|
|
|
@ -37,6 +37,8 @@ void init_registers_i386 (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct i386_debug_reg_state debug_reg_state;
|
static struct i386_debug_reg_state debug_reg_state;
|
||||||
|
static unsigned dr_status_mirror;
|
||||||
|
static unsigned dr_control_mirror;
|
||||||
|
|
||||||
static int debug_registers_changed = 0;
|
static int debug_registers_changed = 0;
|
||||||
static int debug_registers_used = 0;
|
static int debug_registers_used = 0;
|
||||||
|
@ -56,6 +58,14 @@ i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
|
||||||
debug_registers_used = 1;
|
debug_registers_used = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CORE_ADDR
|
||||||
|
i386_dr_low_get_addr (int regnum)
|
||||||
|
{
|
||||||
|
gdb_assert (DR_FIRSTADDR <= regnum && regnum < DR_LASTADDR);
|
||||||
|
|
||||||
|
return debug_reg_state.dr_mirror[regnum];
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the inferior's DR7 debug control register from STATE. */
|
/* Update the inferior's DR7 debug control register from STATE. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -68,14 +78,21 @@ i386_dr_low_set_control (const struct i386_debug_reg_state *state)
|
||||||
debug_registers_used = 1;
|
debug_registers_used = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
i386_dr_low_get_control (void)
|
||||||
|
{
|
||||||
|
return dr_control_mirror;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the value of the DR6 debug status register from the inferior
|
/* Get the value of the DR6 debug status register from the inferior
|
||||||
and record it in STATE. */
|
and record it in STATE. */
|
||||||
|
|
||||||
void
|
unsigned
|
||||||
i386_dr_low_get_status (struct i386_debug_reg_state *state)
|
i386_dr_low_get_status (void)
|
||||||
{
|
{
|
||||||
/* We don't need to do anything here, the last call to thread_rec for
|
/* We don't need to do anything here, the last call to thread_rec for
|
||||||
current_event.dwThreadId id has already set it. */
|
current_event.dwThreadId id has already set it. */
|
||||||
|
return dr_status_mirror;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Watchpoint support. */
|
/* Watchpoint support. */
|
||||||
|
@ -133,6 +150,8 @@ i386_initial_stuff (void)
|
||||||
i386_low_init_dregs (&debug_reg_state);
|
i386_low_init_dregs (&debug_reg_state);
|
||||||
debug_registers_changed = 0;
|
debug_registers_changed = 0;
|
||||||
debug_registers_used = 0;
|
debug_registers_used = 0;
|
||||||
|
dr_status_mirror = 0;
|
||||||
|
dr_control_mirror = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -171,8 +190,8 @@ i386_get_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
|
||||||
dr->dr_mirror[1] = th->context.Dr1;
|
dr->dr_mirror[1] = th->context.Dr1;
|
||||||
dr->dr_mirror[2] = th->context.Dr2;
|
dr->dr_mirror[2] = th->context.Dr2;
|
||||||
dr->dr_mirror[3] = th->context.Dr3;
|
dr->dr_mirror[3] = th->context.Dr3;
|
||||||
dr->dr_status_mirror = th->context.Dr6;
|
dr_status_mirror = th->context.Dr6;
|
||||||
dr->dr_control_mirror = th->context.Dr7;
|
dr_control_mirror = th->context.Dr7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,9 +205,9 @@ i386_set_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
|
||||||
th->context.Dr1 = dr->dr_mirror[1];
|
th->context.Dr1 = dr->dr_mirror[1];
|
||||||
th->context.Dr2 = dr->dr_mirror[2];
|
th->context.Dr2 = dr->dr_mirror[2];
|
||||||
th->context.Dr3 = dr->dr_mirror[3];
|
th->context.Dr3 = dr->dr_mirror[3];
|
||||||
/* th->context.Dr6 = dr->dr_status_mirror;
|
/* th->context.Dr6 = dr_status_mirror;
|
||||||
FIXME: should we set dr6 also ?? */
|
FIXME: should we set dr6 also ?? */
|
||||||
th->context.Dr7 = dr->dr_control_mirror;
|
th->context.Dr7 = dr_control_mirror;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetThreadContext (th->h, &th->context);
|
SetThreadContext (th->h, &th->context);
|
||||||
|
@ -208,9 +227,9 @@ i386_thread_added (win32_thread_info *th)
|
||||||
th->context.Dr1 = dr->dr_mirror[1];
|
th->context.Dr1 = dr->dr_mirror[1];
|
||||||
th->context.Dr2 = dr->dr_mirror[2];
|
th->context.Dr2 = dr->dr_mirror[2];
|
||||||
th->context.Dr3 = dr->dr_mirror[3];
|
th->context.Dr3 = dr->dr_mirror[3];
|
||||||
/* th->context.Dr6 = dr->dr_status_mirror;
|
/* th->context.Dr6 = dr_status_mirror;
|
||||||
FIXME: should we set dr6 also ?? */
|
FIXME: should we set dr6 also ?? */
|
||||||
th->context.Dr7 = dr->dr_control_mirror;
|
th->context.Dr7 = dr_control_mirror;
|
||||||
|
|
||||||
SetThreadContext (th->h, &th->context);
|
SetThreadContext (th->h, &th->context);
|
||||||
th->context.ContextFlags = 0;
|
th->context.ContextFlags = 0;
|
||||||
|
|
Loading…
Reference in New Issue