X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fi386-nat.c;h=2f80a6eb7ec0d9bedf9a3aa3fddcb3aa8e07fdb5;hb=2117c711ae07700adb57ea5b5ca61e4c32d7e3d2;hp=e27a1a042412a6f959004ed039368f04bc8fe90a;hpb=75d12218648d04459fc1b98644e807381e514248;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/i386-nat.c b/gdb/i386-nat.c index e27a1a0424..2f80a6eb7e 100644 --- a/gdb/i386-nat.c +++ b/gdb/i386-nat.c @@ -1,7 +1,6 @@ /* Native-dependent code for the i386. - Copyright (C) 2001, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -18,13 +17,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "i386-nat.h" #include "defs.h" +#include "i386-nat.h" #include "breakpoint.h" #include "command.h" #include "gdbcmd.h" #include "target.h" #include "gdb_assert.h" +#include "inferior.h" /* Support for hardware watchpoints and breakpoints using the i386 debug registers. @@ -43,11 +43,6 @@ struct i386_dr_low_type i386_dr_low; /* Support for 8-byte wide hw watchpoints. */ #define TARGET_HAS_DR_LEN_8 (i386_dr_low.debug_register_length == 8) -/* Debug registers' indices. */ -#define DR_NADDR 4 /* The number of debug address registers. */ -#define DR_STATUS 6 /* Index of debug status register (DR6). */ -#define DR_CONTROL 7 /* Index of debug control register (DR7). */ - /* DR7 Debug Control register fields. */ /* How many bits to skip in DR7 to get to R/W and LEN fields. */ @@ -158,42 +153,104 @@ struct i386_dr_low_type i386_dr_low; /* A macro to loop over all debug registers. */ #define ALL_DEBUG_REGISTERS(i) for (i = 0; i < DR_NADDR; i++) +/* Per-process data. We don't bind this to a per-inferior registry + because of targets like x86 GNU/Linux that need to keep track of + processes that aren't bound to any inferior (e.g., fork children, + checkpoints). */ -/* Global state needed to track h/w watchpoints. */ - -struct i386_debug_reg_state +struct i386_process_info { - /* Mirror the inferior's DRi registers. We keep the status and - 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]; - unsigned dr_status_mirror, dr_control_mirror; - - /* Reference counts for each debug register. */ - int dr_ref_count[DR_NADDR]; + /* Linked list. */ + struct i386_process_info *next; + + /* The process identifier. */ + pid_t pid; + + /* Copy of i386 hardware debug registers. */ + struct i386_debug_reg_state state; }; -/* Clear the reference counts and forget everything we knew about the - debug registers. */ +static struct i386_process_info *i386_process_list = NULL; -static void -i386_init_dregs (struct i386_debug_reg_state *state) +/* Find process data for process PID. */ + +static struct i386_process_info * +i386_find_process_pid (pid_t pid) { - int i; + struct i386_process_info *proc; - ALL_DEBUG_REGISTERS (i) + for (proc = i386_process_list; proc; proc = proc->next) + if (proc->pid == pid) + return proc; + + return NULL; +} + +/* Add process data for process PID. Returns newly allocated info + object. */ + +static struct i386_process_info * +i386_add_process (pid_t pid) +{ + struct i386_process_info *proc; + + proc = xcalloc (1, sizeof (*proc)); + proc->pid = pid; + + proc->next = i386_process_list; + i386_process_list = proc; + + return proc; +} + +/* Get data specific info for process PID, creating it if necessary. + Never returns NULL. */ + +static struct i386_process_info * +i386_process_info_get (pid_t pid) +{ + struct i386_process_info *proc; + + proc = i386_find_process_pid (pid); + if (proc == NULL) + proc = i386_add_process (pid); + + return proc; +} + +/* Get debug registers state for process PID. */ + +struct i386_debug_reg_state * +i386_debug_reg_state (pid_t pid) +{ + return &i386_process_info_get (pid)->state; +} + +/* See declaration in i386-nat.h. */ + +void +i386_forget_process (pid_t pid) +{ + struct i386_process_info *proc, **proc_link; + + proc = i386_process_list; + proc_link = &i386_process_list; + + while (proc != NULL) { - state->dr_mirror[i] = 0; - state->dr_ref_count[i] = 0; + if (proc->pid == pid) + { + *proc_link = proc->next; + + xfree (proc); + return; + } + + proc_link = &proc->next; + proc = *proc_link; } - state->dr_control_mirror = 0; - state->dr_status_mirror = 0; } -static struct i386_debug_reg_state dr_mirror; - /* Whether or not to print the mirrored debug registers. */ static int maint_show_dr; @@ -244,7 +301,8 @@ static int i386_handle_nonaligned_watchpoint (struct i386_debug_reg_state *state void i386_cleanup_dregs (void) { - i386_init_dregs (&dr_mirror); + /* Starting from scratch has the same effect. */ + i386_forget_process (ptid_get_pid (inferior_ptid)); } /* Print the values of the mirrored debug registers. This is called @@ -256,7 +314,7 @@ i386_show_dr (struct i386_debug_reg_state *state, const char *func, CORE_ADDR addr, int len, enum target_hw_bp_type type) { - int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; + int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8; int i; puts_unfiltered (func); @@ -508,35 +566,22 @@ Invalid value %d of operation in i386_handle_nonaligned_watchpoint.\n"), static void i386_update_inferior_debug_regs (struct i386_debug_reg_state *new_state) { + struct i386_debug_reg_state *state + = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); int i; ALL_DEBUG_REGISTERS (i) { - if (I386_DR_VACANT (new_state, i) != I386_DR_VACANT (&dr_mirror, i)) - { - if (!I386_DR_VACANT (new_state, i)) - { - i386_dr_low.set_addr (i, new_state->dr_mirror[i]); - - /* Only a sanity check for leftover bits (set possibly only - by inferior). */ - if (i386_dr_low.unset_status) - i386_dr_low.unset_status (I386_DR_WATCH_MASK (i)); - } - else - { - if (i386_dr_low.reset_addr) - i386_dr_low.reset_addr (i); - } - } + if (I386_DR_VACANT (new_state, i) != I386_DR_VACANT (state, i)) + i386_dr_low.set_addr (i, new_state->dr_mirror[i]); else - gdb_assert (new_state->dr_mirror[i] == dr_mirror.dr_mirror[i]); + gdb_assert (new_state->dr_mirror[i] == state->dr_mirror[i]); } - if (new_state->dr_control_mirror != dr_mirror.dr_control_mirror) + if (new_state->dr_control_mirror != state->dr_control_mirror) i386_dr_low.set_control (new_state->dr_control_mirror); - dr_mirror = *new_state; + *state = *new_state; } /* Insert a watchpoint to watch a memory region which starts at @@ -544,13 +589,16 @@ i386_update_inferior_debug_regs (struct i386_debug_reg_state *new_state) of the type TYPE. Return 0 on success, -1 on failure. */ static int -i386_insert_watchpoint (CORE_ADDR addr, int len, int type, +i386_insert_watchpoint (struct target_ops *self, + CORE_ADDR addr, int len, int type, struct expression *cond) { + struct i386_debug_reg_state *state + = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); int retval; /* Work on a local copy of the debug registers, and on success, commit the change back to the inferior. */ - struct i386_debug_reg_state local_state = dr_mirror; + struct i386_debug_reg_state local_state = *state; if (type == hw_read) return 1; /* unsupported */ @@ -571,7 +619,7 @@ i386_insert_watchpoint (CORE_ADDR addr, int len, int type, i386_update_inferior_debug_regs (&local_state); if (maint_show_dr) - i386_show_dr (&dr_mirror, "insert_watchpoint", addr, len, type); + i386_show_dr (state, "insert_watchpoint", addr, len, type); return retval; } @@ -580,13 +628,16 @@ i386_insert_watchpoint (CORE_ADDR addr, int len, int type, address ADDR, whose length is LEN bytes, and for accesses of the type TYPE. Return 0 on success, -1 on failure. */ static int -i386_remove_watchpoint (CORE_ADDR addr, int len, int type, +i386_remove_watchpoint (struct target_ops *self, + CORE_ADDR addr, int len, int type, struct expression *cond) { + struct i386_debug_reg_state *state + = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); int retval; /* Work on a local copy of the debug registers, and on success, commit the change back to the inferior. */ - struct i386_debug_reg_state local_state = dr_mirror; + struct i386_debug_reg_state local_state = *state; if (((len != 1 && len !=2 && len !=4) && !(TARGET_HAS_DR_LEN_8 && len == 8)) || addr % len != 0) @@ -604,7 +655,7 @@ i386_remove_watchpoint (CORE_ADDR addr, int len, int type, i386_update_inferior_debug_regs (&local_state); if (maint_show_dr) - i386_show_dr (&dr_mirror, "remove_watchpoint", addr, len, type); + i386_show_dr (state, "remove_watchpoint", addr, len, type); return retval; } @@ -613,13 +664,16 @@ i386_remove_watchpoint (CORE_ADDR addr, int len, int type, address ADDR and whose length is LEN bytes. */ static int -i386_region_ok_for_watchpoint (CORE_ADDR addr, int len) +i386_region_ok_for_watchpoint (struct target_ops *self, + CORE_ADDR addr, int len) { + struct i386_debug_reg_state *state + = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); int nregs; /* Compute how many aligned watchpoints we would need to cover this region. */ - nregs = i386_handle_nonaligned_watchpoint (&dr_mirror, + nregs = i386_handle_nonaligned_watchpoint (state, WP_COUNT, addr, len, hw_write); return nregs <= DR_NADDR ? 1 : 0; } @@ -631,38 +685,73 @@ i386_region_ok_for_watchpoint (CORE_ADDR addr, int len) static int i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) { + struct i386_debug_reg_state *state + = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); CORE_ADDR addr = 0; int i; int rc = 0; + /* The current thread's DR_STATUS. We always need to read this to + check whether some watchpoint caused the trap. */ unsigned status; - unsigned control; - struct i386_debug_reg_state *state = &dr_mirror; - - dr_mirror.dr_status_mirror = i386_dr_low.get_status (); - status = dr_mirror.dr_status_mirror; - control = dr_mirror.dr_control_mirror; + /* We need DR_CONTROL as well, but only iff DR_STATUS indicates a + data breakpoint trap. Only fetch it when necessary, to avoid an + unnecessary extra syscall when no watchpoint triggered. */ + int control_p = 0; + unsigned control = 0; + + /* In non-stop/async, threads can be running while we change the + STATE (and friends). Say, we set a watchpoint, and let threads + resume. Now, say you delete the watchpoint, or add/remove + watchpoints such that STATE changes while threads are running. + On targets that support non-stop, inserting/deleting watchpoints + updates the STATE only. It does not update the real thread's + debug registers; that's only done prior to resume. Instead, if + threads are running when the mirror changes, a temporary and + transparent stop on all threads is forced so they can get their + copy of the debug registers updated on re-resume. Now, say, + a thread hit a watchpoint before having been updated with the new + STATE contents, and we haven't yet handled the corresponding + SIGTRAP. If we trusted STATE below, we'd mistake the real + trapped address (from the last time we had updated debug + registers in the thread) with whatever was currently in STATE. + So to fix this, STATE always represents intention, what we _want_ + threads to have in debug registers. To get at the address and + cause of the trap, we need to read the state the thread still has + in its debug registers. + + In sum, always get the current debug register values the current + thread has, instead of trusting the global mirror. If the thread + was running when we last changed watchpoints, the mirror no + longer represents what was set in this thread's debug + registers. */ + status = i386_dr_low.get_status (); ALL_DEBUG_REGISTERS(i) { - if (I386_DR_WATCH_HIT (status, i) - /* This second condition makes sure DRi is set up for a data - watchpoint, not a hardware breakpoint. The reason is - that GDB doesn't call the target_stopped_data_address - method except for data watchpoints. In other words, I'm - being paranoiac. */ - && I386_DR_GET_RW_LEN (control, i) != 0 - /* This third condition makes sure DRi is not vacant, this - avoids false positives in windows-nat.c. */ - && !I386_DR_VACANT (state, i)) + if (!I386_DR_WATCH_HIT (status, i)) + continue; + + if (!control_p) + { + control = i386_dr_low.get_control (); + control_p = 1; + } + + /* This second condition makes sure DRi is set up for a data + watchpoint, not a hardware breakpoint. The reason is that + GDB doesn't call the target_stopped_data_address method + except for data watchpoints. In other words, I'm being + paranoiac. */ + if (I386_DR_GET_RW_LEN (control, i) != 0) { - addr = state->dr_mirror[i]; + addr = i386_dr_low.get_addr (i); rc = 1; if (maint_show_dr) - i386_show_dr (&dr_mirror, "watchpoint_hit", addr, -1, hw_write); + i386_show_dr (state, "watchpoint_hit", addr, -1, hw_write); } } if (maint_show_dr && addr == 0) - i386_show_dr (&dr_mirror, "stopped_data_addr", 0, 0, hw_write); + i386_show_dr (state, "stopped_data_addr", 0, 0, hw_write); if (rc) *addr_p = addr; @@ -670,25 +759,33 @@ i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) } static int -i386_stopped_by_watchpoint (void) +i386_stopped_by_watchpoint (struct target_ops *ops) { CORE_ADDR addr = 0; - return i386_stopped_data_address (¤t_target, &addr); + return i386_stopped_data_address (ops, &addr); } /* Insert a hardware-assisted breakpoint at BP_TGT->placed_address. Return 0 on success, EBUSY on failure. */ static int -i386_insert_hw_breakpoint (struct gdbarch *gdbarch, +i386_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, struct bp_target_info *bp_tgt) { + struct i386_debug_reg_state *state + = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); unsigned len_rw = i386_length_and_rw_bits (1, hw_execute); CORE_ADDR addr = bp_tgt->placed_address; - int retval = i386_insert_aligned_watchpoint (&dr_mirror, + /* Work on a local copy of the debug registers, and on success, + commit the change back to the inferior. */ + struct i386_debug_reg_state local_state = *state; + int retval = i386_insert_aligned_watchpoint (&local_state, addr, len_rw) ? EBUSY : 0; + if (retval == 0) + i386_update_inferior_debug_regs (&local_state); + if (maint_show_dr) - i386_show_dr (&dr_mirror, "insert_hwbp", addr, 1, hw_execute); + i386_show_dr (state, "insert_hwbp", addr, 1, hw_execute); return retval; } @@ -697,16 +794,24 @@ i386_insert_hw_breakpoint (struct gdbarch *gdbarch, Return 0 on success, -1 on failure. */ static int -i386_remove_hw_breakpoint (struct gdbarch *gdbarch, +i386_remove_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, struct bp_target_info *bp_tgt) { + struct i386_debug_reg_state *state + = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); unsigned len_rw = i386_length_and_rw_bits (1, hw_execute); CORE_ADDR addr = bp_tgt->placed_address; - int retval = i386_remove_aligned_watchpoint (&dr_mirror, + /* Work on a local copy of the debug registers, and on success, + commit the change back to the inferior. */ + struct i386_debug_reg_state local_state = *state; + int retval = i386_remove_aligned_watchpoint (&local_state, addr, len_rw); + if (retval == 0) + i386_update_inferior_debug_regs (&local_state); + if (maint_show_dr) - i386_show_dr (&dr_mirror, "remove_hwbp", addr, 1, hw_execute); + i386_show_dr (state, "remove_hwbp", addr, 1, hw_execute); return retval; } @@ -729,7 +834,8 @@ i386_remove_hw_breakpoint (struct gdbarch *gdbarch, sharing implemented via reference counts in i386-nat.c. */ static int -i386_can_use_hw_breakpoint (int type, int cnt, int othertype) +i386_can_use_hw_breakpoint (struct target_ops *self, + int type, int cnt, int othertype) { return 1; }