summaryrefslogtreecommitdiff
path: root/gdb/ia64-linux-nat.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2007-03-28 18:56:07 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2007-03-28 18:56:07 +0000
commit5946c640d034763f0bbdba9272e0433578909073 (patch)
tree685efd62ea46bcd69c6c51851e05450f61af6e5b /gdb/ia64-linux-nat.c
parent55915e6ac40b1eda25f7b56953caa1c34d6222d5 (diff)
downloadgdb-5946c640d034763f0bbdba9272e0433578909073.tar.gz
* arch-utils.c (legacy_pc_in_sigtramp): Remove.
* arch-utils.h (legacy_pc_in_sigtramp): Remove. * config/ia64/linux.mt (DEPRECATED_TM_FILE): Remove. * config/ia64/tm-linux.h: Remove file. * ia64-tdep.h (struct gdbarch_tdep): Add pc_in_sigtramp callback. * ia64-tdep.c (ia64_sigtramp_frame_sniffer): Use it instead of legacy_pc_in_sigtramp. (ia64_gdbarch_init): Initialize tdep->pc_in_sigtramp. * ia64-linux-tdep.c (ia64_linux_pc_in_sigtramp): Make static. Remove func_name argument. (ia64_linux_init_abi): Install it as tdep->pc_in_sigtramp. * infrun.c (HAVE_STEPPABLE_WATCHPOINT): Do not redefine. * target.c (update_current_target): Add to_have_steppable_watchpoint. * target.h (struct target_ops): Add to_have_steppable_watchpoint. (HAVE_STEPPABLE_WATCHPOINT): Define. * config/ia64/linux.mh (NATDEPFILES): Remove core-aout.o. * config/ia64/nm-linux.h (KERNEL_U_ADDR, U_REGS_OFFSET, CANNOT_FETCH_REGISTER, CANNOT_STORE_REGISTER, TARGET_CAN_USE_HARDWARE_WATCHPOINT, HAVE_STEPPABLE_WATCHPOINT, STOPPED_BY_WATCHPOINT, target_stopped_data_address, target_insert_watchpoint, target_remove_watchpoint): Remove. (FETCH_INFERIOR_REGISTERS): Define. * ia64-linux-nat.c (ia64_register_addr): Make static. (ia64_cannot_fetch_register, ia64_cannot_store_register): Likewise. (ia64_linux_insert_watchpoint): Make static. Remove ptid_p argument. (ia64_linux_remove_watchpoint): Likewise. Add type argument. (ia64_linux_stopped_data_address): Make static. Add target_ops. (ia64_linux_stopped_by_watchpoint): Make static. (ia64_linux_can_use_hw_breakpoint): New function. (ia64_linux_fetch_register, ia64_linux_fetch_registers): Likewise. (ia64_linux_store_register, ia64_linux_store_registers): Likewise. (_initialize_ia64_linux_nat): Install register and watchpoint ops.
Diffstat (limited to 'gdb/ia64-linux-nat.c')
-rw-r--r--gdb/ia64-linux-nat.c169
1 files changed, 155 insertions, 14 deletions
diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c
index bce6e55fa47..989550a8120 100644
--- a/gdb/ia64-linux-nat.c
+++ b/gdb/ia64-linux-nat.c
@@ -303,8 +303,8 @@ static int u_offsets[] =
-1, -1, -1, -1, -1, -1, -1, -1,
};
-CORE_ADDR
-register_addr (int regno, CORE_ADDR blockend)
+static CORE_ADDR
+ia64_register_addr (int regno)
{
CORE_ADDR addr;
@@ -319,14 +319,14 @@ register_addr (int regno, CORE_ADDR blockend)
return addr;
}
-int ia64_cannot_fetch_register (regno)
- int regno;
+static int
+ia64_cannot_fetch_register (int regno)
{
return regno < 0 || regno >= NUM_REGS || u_offsets[regno] == -1;
}
-int ia64_cannot_store_register (regno)
- int regno;
+static int
+ia64_cannot_store_register (int regno)
{
/* Rationale behind not permitting stores to bspstore...
@@ -561,9 +561,10 @@ is_power_of_2 (int val)
return onecount <= 1;
}
-int
-ia64_linux_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
+static int
+ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
{
+ ptid_t ptid = inferior_ptid;
int idx;
long dbr_addr, dbr_mask;
int max_watchpoints = 4;
@@ -608,9 +609,10 @@ ia64_linux_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
return 0;
}
-int
-ia64_linux_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
+static int
+ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
{
+ ptid_t ptid = inferior_ptid;
int idx;
long dbr_addr, dbr_mask;
int max_watchpoints = 4;
@@ -632,8 +634,8 @@ ia64_linux_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
return -1;
}
-int
-ia64_linux_stopped_data_address (CORE_ADDR *addr_p)
+static int
+ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
{
CORE_ADDR psr;
int tid;
@@ -660,13 +662,130 @@ ia64_linux_stopped_data_address (CORE_ADDR *addr_p)
return 1;
}
-int
+static int
ia64_linux_stopped_by_watchpoint (void)
{
CORE_ADDR addr;
- return ia64_linux_stopped_data_address (&addr);
+ return ia64_linux_stopped_data_address (&current_target, &addr);
+}
+
+static int
+ia64_linux_can_use_hw_breakpoint (int type, int cnt, int othertype)
+{
+ return 1;
+}
+
+
+/* Fetch register REGNUM from the inferior. */
+
+static void
+ia64_linux_fetch_register (int regnum)
+{
+ CORE_ADDR addr;
+ size_t size;
+ PTRACE_TYPE_RET *buf;
+ int pid, i;
+
+ if (ia64_cannot_fetch_register (regnum))
+ {
+ regcache_raw_supply (current_regcache, regnum, NULL);
+ return;
+ }
+
+ /* Cater for systems like GNU/Linux, that implement threads as
+ separate processes. */
+ pid = ptid_get_lwp (inferior_ptid);
+ if (pid == 0)
+ pid = ptid_get_pid (inferior_ptid);
+
+ /* This isn't really an address, but ptrace thinks of it as one. */
+ addr = ia64_register_addr (regnum);
+ size = register_size (current_gdbarch, regnum);
+
+ gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
+ buf = alloca (size);
+
+ /* Read the register contents from the inferior a chunk at a time. */
+ for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+ {
+ errno = 0;
+ buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)addr, 0);
+ if (errno != 0)
+ error (_("Couldn't read register %s (#%d): %s."),
+ REGISTER_NAME (regnum), regnum, safe_strerror (errno));
+
+ addr += sizeof (PTRACE_TYPE_RET);
+ }
+ regcache_raw_supply (current_regcache, regnum, buf);
+}
+
+/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
+ for all registers. */
+
+static void
+ia64_linux_fetch_registers (int regnum)
+{
+ if (regnum == -1)
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ ia64_linux_fetch_register (regnum);
+ else
+ ia64_linux_fetch_register (regnum);
+}
+
+/* Store register REGNUM into the inferior. */
+
+static void
+ia64_linux_store_register (int regnum)
+{
+ CORE_ADDR addr;
+ size_t size;
+ PTRACE_TYPE_RET *buf;
+ int pid, i;
+
+ if (ia64_cannot_store_register (regnum))
+ return;
+
+ /* Cater for systems like GNU/Linux, that implement threads as
+ separate processes. */
+ pid = ptid_get_lwp (inferior_ptid);
+ if (pid == 0)
+ pid = ptid_get_pid (inferior_ptid);
+
+ /* This isn't really an address, but ptrace thinks of it as one. */
+ addr = ia64_register_addr (regnum);
+ size = register_size (current_gdbarch, regnum);
+
+ gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
+ buf = alloca (size);
+
+ /* Write the register contents into the inferior a chunk at a time. */
+ regcache_raw_collect (current_regcache, regnum, buf);
+ for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)addr, buf[i]);
+ if (errno != 0)
+ error (_("Couldn't write register %s (#%d): %s."),
+ REGISTER_NAME (regnum), regnum, safe_strerror (errno));
+
+ addr += sizeof (PTRACE_TYPE_RET);
+ }
}
+/* Store register REGNUM back into the inferior. If REGNUM is -1, do
+ this for all registers. */
+
+static void
+ia64_linux_store_registers (int regnum)
+{
+ if (regnum == -1)
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ ia64_linux_store_register (regnum);
+ else
+ ia64_linux_store_register (regnum);
+}
+
+
static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object,
const char *, gdb_byte *, const gdb_byte *,
ULONGEST, LONGEST);
@@ -695,10 +814,32 @@ _initialize_ia64_linux_nat (void)
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
+ /* Override the default fetch/store register routines. */
+ t->to_fetch_registers = ia64_linux_fetch_registers;
+ t->to_store_registers = ia64_linux_store_registers;
+
/* Override the default to_xfer_partial. */
super_xfer_partial = t->to_xfer_partial;
t->to_xfer_partial = ia64_linux_xfer_partial;
+ /* Override watchpoint routines. */
+
+ /* The IA-64 architecture can step over a watch point (without triggering
+ it again) if the "dd" (data debug fault disable) bit in the processor
+ status word is set.
+
+ This PSR bit is set in ia64_linux_stopped_by_watchpoint when the
+ code there has determined that a hardware watchpoint has indeed
+ been hit. The CPU will then be able to execute one instruction
+ without triggering a watchpoint. */
+
+ t->to_have_steppable_watchpoint = 1;
+ t->to_can_use_hw_breakpoint = ia64_linux_can_use_hw_breakpoint;
+ t->to_stopped_by_watchpoint = ia64_linux_stopped_by_watchpoint;
+ t->to_stopped_data_address = ia64_linux_stopped_data_address;
+ t->to_insert_watchpoint = ia64_linux_insert_watchpoint;
+ t->to_remove_watchpoint = ia64_linux_remove_watchpoint;
+
/* Register the target. */
linux_nat_add_target (t);
}