Index: gdb/mips-linux-nat.c |
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c |
index b9f7f1dc638fb8c57329d21e7927053312cf660c..9246741c7107ac49a64131d1df47ab3b56af05cb 100644 |
--- a/gdb/mips-linux-nat.c |
+++ b/gdb/mips-linux-nat.c |
@@ -1,6 +1,6 @@ |
/* Native-dependent code for GNU/Linux on MIPS processors. |
- Copyright (C) 2001-2012 Free Software Foundation, Inc. |
+ Copyright (C) 2001-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -34,6 +34,9 @@ |
#include <sgidefs.h> |
#include <sys/ptrace.h> |
+#include <asm/ptrace.h> |
+ |
+#include "mips-linux-watch.h" |
#include "features/mips-linux.c" |
#include "features/mips-dsp-linux.c" |
@@ -60,7 +63,7 @@ static void (*super_fetch_registers) (struct target_ops *, |
static void (*super_store_registers) (struct target_ops *, |
struct regcache *, int); |
-static void (*super_close) (int); |
+static void (*super_close) (void); |
/* Map gdb internal register number to ptrace ``address''. |
These ``addresses'' are normally defined in <asm/ptrace.h>. |
@@ -326,7 +329,7 @@ mips64_linux_regsets_store_registers (struct target_ops *ops, |
have_dsp = mips_regnum (gdbarch)->dspctl != -1; |
if (!have_dsp) |
is_dsp = 0; |
- if (regno >= mips_regnum (gdbarch)->dspacc |
+ else if (regno >= mips_regnum (gdbarch)->dspacc |
&& regno < mips_regnum (gdbarch)->dspacc + 6) |
is_dsp = 1; |
else if (regno == mips_regnum (gdbarch)->dspctl) |
@@ -460,70 +463,6 @@ mips_linux_read_description (struct target_ops *ops) |
return have_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux; |
} |
-#ifndef PTRACE_GET_WATCH_REGS |
-# define PTRACE_GET_WATCH_REGS 0xd0 |
-#endif |
- |
-#ifndef PTRACE_SET_WATCH_REGS |
-# define PTRACE_SET_WATCH_REGS 0xd1 |
-#endif |
- |
-#define W_BIT 0 |
-#define R_BIT 1 |
-#define I_BIT 2 |
- |
-#define W_MASK (1 << W_BIT) |
-#define R_MASK (1 << R_BIT) |
-#define I_MASK (1 << I_BIT) |
- |
-#define IRW_MASK (I_MASK | R_MASK | W_MASK) |
- |
-enum pt_watch_style { |
- pt_watch_style_mips32, |
- pt_watch_style_mips64 |
-}; |
- |
-#define MAX_DEBUG_REGISTER 8 |
- |
-/* A value of zero in a watchlo indicates that it is available. */ |
- |
-struct mips32_watch_regs |
-{ |
- uint32_t watchlo[MAX_DEBUG_REGISTER]; |
- /* Lower 16 bits of watchhi. */ |
- uint16_t watchhi[MAX_DEBUG_REGISTER]; |
- /* Valid mask and I R W bits. |
- * bit 0 -- 1 if W bit is usable. |
- * bit 1 -- 1 if R bit is usable. |
- * bit 2 -- 1 if I bit is usable. |
- * bits 3 - 11 -- Valid watchhi mask bits. |
- */ |
- uint16_t watch_masks[MAX_DEBUG_REGISTER]; |
- /* The number of valid watch register pairs. */ |
- uint32_t num_valid; |
- /* There is confusion across gcc versions about structure alignment, |
- so we force 8 byte alignment for these structures so they match |
- the kernel even if it was build with a different gcc version. */ |
-} __attribute__ ((aligned (8))); |
- |
-struct mips64_watch_regs |
-{ |
- uint64_t watchlo[MAX_DEBUG_REGISTER]; |
- uint16_t watchhi[MAX_DEBUG_REGISTER]; |
- uint16_t watch_masks[MAX_DEBUG_REGISTER]; |
- uint32_t num_valid; |
-} __attribute__ ((aligned (8))); |
- |
-struct pt_watch_regs |
-{ |
- enum pt_watch_style style; |
- union |
- { |
- struct mips32_watch_regs mips32; |
- struct mips64_watch_regs mips64; |
- }; |
-}; |
- |
/* -1 if the kernel and/or CPU do not support watch registers. |
1 if watch_readback is valid and we can read style, num_valid |
and the masks. |
@@ -535,18 +474,6 @@ static int watch_readback_valid; |
static struct pt_watch_regs watch_readback; |
-/* We keep list of all watchpoints we should install and calculate the |
- watch register values each time the list changes. This allows for |
- easy sharing of watch registers for more than one watchpoint. */ |
- |
-struct mips_watchpoint |
-{ |
- CORE_ADDR addr; |
- int len; |
- int type; |
- struct mips_watchpoint *next; |
-}; |
- |
static struct mips_watchpoint *current_watches; |
/* The current set of watch register values for writing the |
@@ -554,131 +481,6 @@ static struct mips_watchpoint *current_watches; |
static struct pt_watch_regs watch_mirror; |
-/* Assuming usable watch registers, return the irw_mask. */ |
- |
-static uint32_t |
-get_irw_mask (struct pt_watch_regs *regs, int set) |
-{ |
- switch (regs->style) |
- { |
- case pt_watch_style_mips32: |
- return regs->mips32.watch_masks[set] & IRW_MASK; |
- case pt_watch_style_mips64: |
- return regs->mips64.watch_masks[set] & IRW_MASK; |
- default: |
- internal_error (__FILE__, __LINE__, |
- _("Unrecognized watch register style")); |
- } |
-} |
- |
-/* Assuming usable watch registers, return the reg_mask. */ |
- |
-static uint32_t |
-get_reg_mask (struct pt_watch_regs *regs, int set) |
-{ |
- switch (regs->style) |
- { |
- case pt_watch_style_mips32: |
- return regs->mips32.watch_masks[set] & ~IRW_MASK; |
- case pt_watch_style_mips64: |
- return regs->mips64.watch_masks[set] & ~IRW_MASK; |
- default: |
- internal_error (__FILE__, __LINE__, |
- _("Unrecognized watch register style")); |
- } |
-} |
- |
-/* Assuming usable watch registers, return the num_valid. */ |
- |
-static uint32_t |
-get_num_valid (struct pt_watch_regs *regs) |
-{ |
- switch (regs->style) |
- { |
- case pt_watch_style_mips32: |
- return regs->mips32.num_valid; |
- case pt_watch_style_mips64: |
- return regs->mips64.num_valid; |
- default: |
- internal_error (__FILE__, __LINE__, |
- _("Unrecognized watch register style")); |
- } |
-} |
- |
-/* Assuming usable watch registers, return the watchlo. */ |
- |
-static CORE_ADDR |
-get_watchlo (struct pt_watch_regs *regs, int set) |
-{ |
- switch (regs->style) |
- { |
- case pt_watch_style_mips32: |
- return regs->mips32.watchlo[set]; |
- case pt_watch_style_mips64: |
- return regs->mips64.watchlo[set]; |
- default: |
- internal_error (__FILE__, __LINE__, |
- _("Unrecognized watch register style")); |
- } |
-} |
- |
-/* Assuming usable watch registers, set a watchlo value. */ |
- |
-static void |
-set_watchlo (struct pt_watch_regs *regs, int set, CORE_ADDR value) |
-{ |
- switch (regs->style) |
- { |
- case pt_watch_style_mips32: |
- /* The cast will never throw away bits as 64 bit addresses can |
- never be used on a 32 bit kernel. */ |
- regs->mips32.watchlo[set] = (uint32_t)value; |
- break; |
- case pt_watch_style_mips64: |
- regs->mips64.watchlo[set] = value; |
- break; |
- default: |
- internal_error (__FILE__, __LINE__, |
- _("Unrecognized watch register style")); |
- } |
-} |
- |
-/* Assuming usable watch registers, return the watchhi. */ |
- |
-static uint32_t |
-get_watchhi (struct pt_watch_regs *regs, int n) |
-{ |
- switch (regs->style) |
- { |
- case pt_watch_style_mips32: |
- return regs->mips32.watchhi[n]; |
- case pt_watch_style_mips64: |
- return regs->mips64.watchhi[n]; |
- default: |
- internal_error (__FILE__, __LINE__, |
- _("Unrecognized watch register style")); |
- } |
-} |
- |
-/* Assuming usable watch registers, set a watchhi value. */ |
- |
-static void |
-set_watchhi (struct pt_watch_regs *regs, int n, uint16_t value) |
-{ |
- switch (regs->style) |
- { |
- case pt_watch_style_mips32: |
- regs->mips32.watchhi[n] = value; |
- break; |
- case pt_watch_style_mips64: |
- regs->mips64.watchhi[n] = value; |
- break; |
- default: |
- internal_error (__FILE__, __LINE__, |
- _("Unrecognized watch register style")); |
- } |
-} |
- |
static void |
mips_show_dr (const char *func, CORE_ADDR addr, |
int len, enum target_hw_bp_type type) |
@@ -688,7 +490,7 @@ mips_show_dr (const char *func, CORE_ADDR addr, |
puts_unfiltered (func); |
if (addr || len) |
printf_unfiltered (" (addr=%s, len=%d, type=%s)", |
- paddress (target_gdbarch, addr), len, |
+ paddress (target_gdbarch (), addr), len, |
type == hw_write ? "data-write" |
: (type == hw_read ? "data-read" |
: (type == hw_access ? "data-read/write" |
@@ -698,70 +500,12 @@ mips_show_dr (const char *func, CORE_ADDR addr, |
for (i = 0; i < MAX_DEBUG_REGISTER; i++) |
printf_unfiltered ("\tDR%d: lo=%s, hi=%s\n", i, |
- paddress (target_gdbarch, |
- get_watchlo (&watch_mirror, i)), |
- paddress (target_gdbarch, |
- get_watchhi (&watch_mirror, i))); |
-} |
- |
-/* Return 1 if watch registers are usable. Cached information is used |
- unless force is true. */ |
- |
-static int |
-mips_linux_read_watch_registers (int force) |
-{ |
- int tid; |
- |
- if (force || watch_readback_valid == 0) |
- { |
- tid = ptid_get_lwp (inferior_ptid); |
- if (ptrace (PTRACE_GET_WATCH_REGS, tid, &watch_readback) == -1) |
- { |
- watch_readback_valid = -1; |
- return 0; |
- } |
- switch (watch_readback.style) |
- { |
- case pt_watch_style_mips32: |
- if (watch_readback.mips32.num_valid == 0) |
- { |
- watch_readback_valid = -1; |
- return 0; |
- } |
- break; |
- case pt_watch_style_mips64: |
- if (watch_readback.mips64.num_valid == 0) |
- { |
- watch_readback_valid = -1; |
- return 0; |
- } |
- break; |
- default: |
- watch_readback_valid = -1; |
- return 0; |
- } |
- /* Watch registers appear to be usable. */ |
- watch_readback_valid = 1; |
- } |
- return (watch_readback_valid == 1) ? 1 : 0; |
-} |
- |
-/* Convert GDB's type to an IRW mask. */ |
- |
-static unsigned |
-type_to_irw (int type) |
-{ |
- switch (type) |
- { |
- case hw_write: |
- return W_MASK; |
- case hw_read: |
- return R_MASK; |
- case hw_access: |
- return (W_MASK | R_MASK); |
- default: |
- return 0; |
- } |
+ paddress (target_gdbarch (), |
+ mips_linux_watch_get_watchlo (&watch_mirror, |
+ i)), |
+ paddress (target_gdbarch (), |
+ mips_linux_watch_get_watchhi (&watch_mirror, |
+ i))); |
} |
/* Target to_can_use_hw_breakpoint implementation. Return 1 if we can |
@@ -773,7 +517,9 @@ mips_linux_can_use_hw_breakpoint (int type, int cnt, int ot) |
int i; |
uint32_t wanted_mask, irw_mask; |
- if (!mips_linux_read_watch_registers (0)) |
+ if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid), |
+ &watch_readback, |
+ &watch_readback_valid, 0)) |
return 0; |
switch (type) |
@@ -791,9 +537,11 @@ mips_linux_can_use_hw_breakpoint (int type, int cnt, int ot) |
return 0; |
} |
- for (i = 0; i < get_num_valid (&watch_readback) && cnt; i++) |
+ for (i = 0; |
+ i < mips_linux_watch_get_num_valid (&watch_readback) && cnt; |
+ i++) |
{ |
- irw_mask = get_irw_mask (&watch_readback, i); |
+ irw_mask = mips_linux_watch_get_irw_mask (&watch_readback, i); |
if ((irw_mask & wanted_mask) == wanted_mask) |
cnt--; |
} |
@@ -810,13 +558,15 @@ mips_linux_stopped_by_watchpoint (void) |
int n; |
int num_valid; |
- if (!mips_linux_read_watch_registers (1)) |
+ if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid), |
+ &watch_readback, |
+ &watch_readback_valid, 1)) |
return 0; |
- num_valid = get_num_valid (&watch_readback); |
+ num_valid = mips_linux_watch_get_num_valid (&watch_readback); |
for (n = 0; n < MAX_DEBUG_REGISTER && n < num_valid; n++) |
- if (get_watchhi (&watch_readback, n) & (R_MASK | W_MASK)) |
+ if (mips_linux_watch_get_watchhi (&watch_readback, n) & (R_MASK | W_MASK)) |
return 1; |
return 0; |
@@ -834,106 +584,6 @@ mips_linux_stopped_data_address (struct target_ops *t, CORE_ADDR *paddr) |
return 0; |
} |
-/* Set any low order bits in mask that are not set. */ |
- |
-static CORE_ADDR |
-fill_mask (CORE_ADDR mask) |
-{ |
- CORE_ADDR f = 1; |
- while (f && f < mask) |
- { |
- mask |= f; |
- f <<= 1; |
- } |
- return mask; |
-} |
- |
-/* Try to add a single watch to the specified registers. Return 1 on |
- success, 0 on failure. */ |
- |
-static int |
-try_one_watch (struct pt_watch_regs *regs, CORE_ADDR addr, |
- int len, unsigned irw) |
-{ |
- CORE_ADDR base_addr, last_byte, break_addr, segment_len; |
- CORE_ADDR mask_bits, t_low, t_low_end; |
- uint16_t t_hi; |
- int i, free_watches; |
- struct pt_watch_regs regs_copy; |
- |
- if (len <= 0) |
- return 0; |
- |
- last_byte = addr + len - 1; |
- mask_bits = fill_mask (addr ^ last_byte) | IRW_MASK; |
- base_addr = addr & ~mask_bits; |
- |
- /* Check to see if it is covered by current registers. */ |
- for (i = 0; i < get_num_valid (regs); i++) |
- { |
- t_low = get_watchlo (regs, i); |
- if (t_low != 0 && irw == ((unsigned)t_low & irw)) |
- { |
- t_hi = get_watchhi (regs, i) | IRW_MASK; |
- t_low &= ~(CORE_ADDR)t_hi; |
- if (addr >= t_low && last_byte <= (t_low + t_hi)) |
- return 1; |
- } |
- } |
- /* Try to find an empty register. */ |
- free_watches = 0; |
- for (i = 0; i < get_num_valid (regs); i++) |
- { |
- t_low = get_watchlo (regs, i); |
- if (t_low == 0 && irw == (get_irw_mask (regs, i) & irw)) |
- { |
- if (mask_bits <= (get_reg_mask (regs, i) | IRW_MASK)) |
- { |
- /* It fits, we'll take it. */ |
- set_watchlo (regs, i, base_addr | irw); |
- set_watchhi (regs, i, mask_bits & ~IRW_MASK); |
- return 1; |
- } |
- else |
- { |
- /* It doesn't fit, but has the proper IRW capabilities. */ |
- free_watches++; |
- } |
- } |
- } |
- if (free_watches > 1) |
- { |
- /* Try to split it across several registers. */ |
- regs_copy = *regs; |
- for (i = 0; i < get_num_valid (®s_copy); i++) |
- { |
- t_low = get_watchlo (®s_copy, i); |
- t_hi = get_reg_mask (®s_copy, i) | IRW_MASK; |
- if (t_low == 0 && irw == (t_hi & irw)) |
- { |
- t_low = addr & ~(CORE_ADDR)t_hi; |
- break_addr = t_low + t_hi + 1; |
- if (break_addr >= addr + len) |
- segment_len = len; |
- else |
- segment_len = break_addr - addr; |
- mask_bits = fill_mask (addr ^ (addr + segment_len - 1)); |
- set_watchlo (®s_copy, i, (addr & ~mask_bits) | irw); |
- set_watchhi (®s_copy, i, mask_bits & ~IRW_MASK); |
- if (break_addr >= addr + len) |
- { |
- *regs = regs_copy; |
- return 1; |
- } |
- len = addr + len - break_addr; |
- addr = break_addr; |
- } |
- } |
- } |
- /* It didn't fit anywhere, we failed. */ |
- return 0; |
-} |
- |
/* Target to_region_ok_for_hw_watchpoint implementation. Return 1 if |
the specified region can be covered by the watch registers. */ |
@@ -943,17 +593,18 @@ mips_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) |
struct pt_watch_regs dummy_regs; |
int i; |
- if (!mips_linux_read_watch_registers (0)) |
+ if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid), |
+ &watch_readback, |
+ &watch_readback_valid, 0)) |
return 0; |
dummy_regs = watch_readback; |
/* Clear them out. */ |
- for (i = 0; i < get_num_valid (&dummy_regs); i++) |
- set_watchlo (&dummy_regs, i, 0); |
- return try_one_watch (&dummy_regs, addr, len, 0); |
+ for (i = 0; i < mips_linux_watch_get_num_valid (&dummy_regs); i++) |
+ mips_linux_watch_set_watchlo (&dummy_regs, i, 0); |
+ return mips_linux_watch_try_one_watch (&dummy_regs, addr, len, 0); |
} |
- |
/* Write the mirrored watch register values for each thread. */ |
static int |
@@ -979,7 +630,9 @@ mips_linux_new_thread (struct lwp_info *lp) |
{ |
int tid; |
- if (!mips_linux_read_watch_registers (0)) |
+ if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid), |
+ &watch_readback, |
+ &watch_readback_valid, 0)) |
return; |
tid = ptid_get_lwp (lp->ptid); |
@@ -987,32 +640,6 @@ mips_linux_new_thread (struct lwp_info *lp) |
perror_with_name (_("Couldn't write debug register")); |
} |
-/* Fill in the watch registers with the currently cached watches. */ |
- |
-static void |
-populate_regs_from_watches (struct pt_watch_regs *regs) |
-{ |
- struct mips_watchpoint *w; |
- int i; |
- |
- /* Clear them out. */ |
- for (i = 0; i < get_num_valid (regs); i++) |
- { |
- set_watchlo (regs, i, 0); |
- set_watchhi (regs, i, 0); |
- } |
- |
- w = current_watches; |
- while (w) |
- { |
- i = try_one_watch (regs, w->addr, w->len, type_to_irw (w->type)); |
- /* They must all fit, because we previously calculated that they |
- would. */ |
- gdb_assert (i); |
- w = w->next; |
- } |
-} |
- |
/* Target to_insert_watchpoint implementation. Try to insert a new |
watch. Return zero on success. */ |
@@ -1027,7 +654,9 @@ mips_linux_insert_watchpoint (CORE_ADDR addr, int len, int type, |
int i; |
int retval; |
- if (!mips_linux_read_watch_registers (0)) |
+ if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid), |
+ &watch_readback, |
+ &watch_readback_valid, 0)) |
return -1; |
if (len <= 0) |
@@ -1035,10 +664,11 @@ mips_linux_insert_watchpoint (CORE_ADDR addr, int len, int type, |
regs = watch_readback; |
/* Add the current watches. */ |
- populate_regs_from_watches (®s); |
+ mips_linux_watch_populate_regs (current_watches, ®s); |
/* Now try to add the new watch. */ |
- if (!try_one_watch (®s, addr, len, type_to_irw (type))) |
+ if (!mips_linux_watch_try_one_watch (®s, addr, len, |
+ mips_linux_watch_type_to_irw (type))) |
return -1; |
/* It fit. Stick it on the end of the list. */ |
@@ -1100,7 +730,7 @@ mips_linux_remove_watchpoint (CORE_ADDR addr, int len, int type, |
gdb_assert (watch_readback_valid == 1); |
watch_mirror = watch_readback; |
- populate_regs_from_watches (&watch_mirror); |
+ mips_linux_watch_populate_regs (current_watches, &watch_mirror); |
retval = write_watchpoint_regs (); |
@@ -1114,7 +744,7 @@ mips_linux_remove_watchpoint (CORE_ADDR addr, int len, int type, |
super implementation. */ |
static void |
-mips_linux_close (int quitting) |
+mips_linux_close (void) |
{ |
struct mips_watchpoint *w; |
struct mips_watchpoint *nw; |
@@ -1130,7 +760,7 @@ mips_linux_close (int quitting) |
current_watches = NULL; |
if (super_close) |
- super_close (quitting); |
+ super_close (); |
} |
void _initialize_mips_linux_nat (void); |