gdb/nat/mips-linux-watch.c - gdb
Functions defined
Source code
- #include "common-defs.h"
- #include <sys/ptrace.h>
- #include "mips-linux-watch.h"
- uint32_t
- mips_linux_watch_get_irw_mask (struct pt_watch_regs *regs, int n)
- {
- switch (regs->style)
- {
- case pt_watch_style_mips32:
- return regs->mips32.watch_masks[n] & IRW_MASK;
- case pt_watch_style_mips64:
- return regs->mips64.watch_masks[n] & IRW_MASK;
- default:
- internal_error (__FILE__, __LINE__,
- _("Unrecognized watch register style"));
- }
- }
- static uint32_t
- get_reg_mask (struct pt_watch_regs *regs, int n)
- {
- switch (regs->style)
- {
- case pt_watch_style_mips32:
- return regs->mips32.watch_masks[n] & ~IRW_MASK;
- case pt_watch_style_mips64:
- return regs->mips64.watch_masks[n] & ~IRW_MASK;
- default:
- internal_error (__FILE__, __LINE__,
- _("Unrecognized watch register style"));
- }
- }
- uint32_t
- mips_linux_watch_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"));
- }
- }
- CORE_ADDR
- mips_linux_watch_get_watchlo (struct pt_watch_regs *regs, int n)
- {
- switch (regs->style)
- {
- case pt_watch_style_mips32:
- return regs->mips32.watchlo[n];
- case pt_watch_style_mips64:
- return regs->mips64.watchlo[n];
- default:
- internal_error (__FILE__, __LINE__,
- _("Unrecognized watch register style"));
- }
- }
- void
- mips_linux_watch_set_watchlo (struct pt_watch_regs *regs, int n,
- CORE_ADDR value)
- {
- switch (regs->style)
- {
- case pt_watch_style_mips32:
-
- regs->mips32.watchlo[n] = (uint32_t) value;
- break;
- case pt_watch_style_mips64:
- regs->mips64.watchlo[n] = value;
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Unrecognized watch register style"));
- }
- }
- uint32_t
- mips_linux_watch_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"));
- }
- }
- void
- mips_linux_watch_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"));
- }
- }
- int
- mips_linux_read_watch_registers (long lwpid,
- struct pt_watch_regs *watch_readback,
- int *watch_readback_valid, int force)
- {
- if (force || *watch_readback_valid == 0)
- {
- if (ptrace (PTRACE_GET_WATCH_REGS, lwpid, 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_readback_valid = 1;
- }
- return (*watch_readback_valid == 1) ? 1 : 0;
- }
- uint32_t
- mips_linux_watch_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;
- }
- }
- static CORE_ADDR
- fill_mask (CORE_ADDR mask)
- {
- CORE_ADDR f = 1;
- while (f && f < mask)
- {
- mask |= f;
- f <<= 1;
- }
- return mask;
- }
- int
- mips_linux_watch_try_one_watch (struct pt_watch_regs *regs,
- CORE_ADDR addr, int len, uint32_t irw)
- {
- CORE_ADDR base_addr, last_byte, break_addr, segment_len;
- CORE_ADDR mask_bits, t_low;
- 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;
-
- for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++)
- {
- t_low = mips_linux_watch_get_watchlo (regs, i);
- if (t_low != 0 && irw == ((uint32_t) t_low & irw))
- {
- t_hi = mips_linux_watch_get_watchhi (regs, i) | IRW_MASK;
- t_low &= ~(CORE_ADDR) t_hi;
- if (addr >= t_low && last_byte <= (t_low + t_hi))
- return 1;
- }
- }
-
- free_watches = 0;
- for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++)
- {
- t_low = mips_linux_watch_get_watchlo (regs, i);
- if (t_low == 0
- && irw == (mips_linux_watch_get_irw_mask (regs, i) & irw))
- {
- if (mask_bits <= (get_reg_mask (regs, i) | IRW_MASK))
- {
-
- mips_linux_watch_set_watchlo (regs, i, base_addr | irw);
- mips_linux_watch_set_watchhi (regs, i, mask_bits & ~IRW_MASK);
- return 1;
- }
- else
- {
-
- free_watches++;
- }
- }
- }
- if (free_watches > 1)
- {
-
- regs_copy = *regs;
- for (i = 0; i < mips_linux_watch_get_num_valid (®s_copy); i++)
- {
- t_low = mips_linux_watch_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));
- mips_linux_watch_set_watchlo (®s_copy, i,
- (addr & ~mask_bits) | irw);
- mips_linux_watch_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;
- }
- }
- }
-
- return 0;
- }
- void
- mips_linux_watch_populate_regs (struct mips_watchpoint *current_watches,
- struct pt_watch_regs *regs)
- {
- struct mips_watchpoint *w;
- int i;
-
- for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++)
- {
- mips_linux_watch_set_watchlo (regs, i, 0);
- mips_linux_watch_set_watchhi (regs, i, 0);
- }
- w = current_watches;
- while (w)
- {
- uint32_t irw = mips_linux_watch_type_to_irw (w->type);
- i = mips_linux_watch_try_one_watch (regs, w->addr, w->len, irw);
-
- gdb_assert (i);
- w = w->next;
- }
- }