* target.h (target_signal_to_string): Make return type const char *.
[deliverable/binutils-gdb.git] / gdb / ia64-linux-nat.c
index dbe6e53c64b352b8603c2efc6c1db4fa5083751c..c2a06ed634826245dab154d8ed7383420500733d 100644 (file)
@@ -1,14 +1,14 @@
 /* Functions specific to running gdb native on IA-64 running
    GNU/Linux.
 
 /* Functions specific to running gdb native on IA-64 running
    GNU/Linux.
 
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "gdb_string.h"
 
 #include "defs.h"
 #include "gdb_string.h"
@@ -304,11 +302,11 @@ static int u_offsets[] =
   };
 
 static CORE_ADDR
   };
 
 static CORE_ADDR
-ia64_register_addr (int regno)
+ia64_register_addr (struct gdbarch *gdbarch, int regno)
 {
   CORE_ADDR addr;
 
 {
   CORE_ADDR addr;
 
-  if (regno < 0 || regno >= NUM_REGS)
+  if (regno < 0 || regno >= gdbarch_num_regs (gdbarch))
     error (_("Invalid register number %d."), regno);
 
   if (u_offsets[regno] == -1)
     error (_("Invalid register number %d."), regno);
 
   if (u_offsets[regno] == -1)
@@ -320,13 +318,15 @@ ia64_register_addr (int regno)
 }
 
 static int
 }
 
 static int
-ia64_cannot_fetch_register (int regno)
+ia64_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
 {
 {
-  return regno < 0 || regno >= NUM_REGS || u_offsets[regno] == -1;
+  return regno < 0
+        || regno >= gdbarch_num_regs (gdbarch)
+        || u_offsets[regno] == -1;
 }
 
 static int
 }
 
 static int
-ia64_cannot_store_register (int regno)
+ia64_cannot_store_register (struct gdbarch *gdbarch, int regno)
 {
   /* Rationale behind not permitting stores to bspstore...
   
 {
   /* Rationale behind not permitting stores to bspstore...
   
@@ -357,7 +357,9 @@ ia64_cannot_store_register (int regno)
      were previously read from the inferior process to be written
      back.)  */
 
      were previously read from the inferior process to be written
      back.)  */
 
-  return regno < 0 || regno >= NUM_REGS || u_offsets[regno] == -1
+  return regno < 0
+        || regno >= gdbarch_num_regs (gdbarch)
+        || u_offsets[regno] == -1
          || regno == IA64_BSPSTORE_REGNUM;
 }
 
          || regno == IA64_BSPSTORE_REGNUM;
 }
 
@@ -479,31 +481,19 @@ fill_fpregset (const struct regcache *regcache,
 static void
 enable_watchpoints_in_psr (ptid_t ptid)
 {
 static void
 enable_watchpoints_in_psr (ptid_t ptid)
 {
-  CORE_ADDR psr;
+  struct regcache *regcache = get_thread_regcache (ptid);
+  ULONGEST psr;
 
 
-  psr = read_register_pid (IA64_PSR_REGNUM, ptid);
+  regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr);
   if (!(psr & IA64_PSR_DB))
     {
       psr |= IA64_PSR_DB;      /* Set the db bit - this enables hardware
                                   watchpoints and breakpoints. */
   if (!(psr & IA64_PSR_DB))
     {
       psr |= IA64_PSR_DB;      /* Set the db bit - this enables hardware
                                   watchpoints and breakpoints. */
-      write_register_pid (IA64_PSR_REGNUM, psr, ptid);
+      regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr);
     }
 }
 
     }
 }
 
-static long
-fetch_debug_register (ptid_t ptid, int idx)
-{
-  long val;
-  int tid;
-
-  tid = TIDGET (ptid);
-  if (tid == 0)
-    tid = PIDGET (ptid);
-
-  val = ptrace (PT_READ_U, tid, (PTRACE_TYPE_ARG3) (PT_DBR + 8 * idx), 0);
-
-  return val;
-}
+static long debug_registers[8];
 
 static void
 store_debug_register (ptid_t ptid, int idx, long val)
 
 static void
 store_debug_register (ptid_t ptid, int idx, long val)
@@ -517,15 +507,6 @@ store_debug_register (ptid_t ptid, int idx, long val)
   (void) ptrace (PT_WRITE_U, tid, (PTRACE_TYPE_ARG3) (PT_DBR + 8 * idx), val);
 }
 
   (void) ptrace (PT_WRITE_U, tid, (PTRACE_TYPE_ARG3) (PT_DBR + 8 * idx), val);
 }
 
-static void
-fetch_debug_register_pair (ptid_t ptid, int idx, long *dbr_addr, long *dbr_mask)
-{
-  if (dbr_addr)
-    *dbr_addr = fetch_debug_register (ptid, 2 * idx);
-  if (dbr_mask)
-    *dbr_mask = fetch_debug_register (ptid, 2 * idx + 1);
-}
-
 static void
 store_debug_register_pair (ptid_t ptid, int idx, long *dbr_addr, long *dbr_mask)
 {
 static void
 store_debug_register_pair (ptid_t ptid, int idx, long *dbr_addr, long *dbr_mask)
 {
@@ -551,7 +532,8 @@ is_power_of_2 (int val)
 static int
 ia64_linux_insert_watchpoint (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;
+  struct lwp_info *lp;
+  ptid_t ptid;
   int idx;
   long dbr_addr, dbr_mask;
   int max_watchpoints = 4;
   int idx;
   long dbr_addr, dbr_mask;
   int max_watchpoints = 4;
@@ -561,7 +543,7 @@ ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
 
   for (idx = 0; idx < max_watchpoints; idx++)
     {
 
   for (idx = 0; idx < max_watchpoints; idx++)
     {
-      fetch_debug_register_pair (ptid, idx, NULL, &dbr_mask);
+      dbr_mask = debug_registers[idx * 2 + 1];
       if ((dbr_mask & (0x3UL << 62)) == 0)
        {
          /* Exit loop if both r and w bits clear */
       if ((dbr_mask & (0x3UL << 62)) == 0)
        {
          /* Exit loop if both r and w bits clear */
@@ -590,8 +572,13 @@ ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
       return -1;
     }
 
       return -1;
     }
 
-  store_debug_register_pair (ptid, idx, &dbr_addr, &dbr_mask);
-  enable_watchpoints_in_psr (ptid);
+  debug_registers[2 * idx] = dbr_addr;
+  debug_registers[2 * idx + 1] = dbr_mask;
+  ALL_LWPS (lp, ptid)
+    {
+      store_debug_register_pair (ptid, idx, &dbr_addr, &dbr_mask);
+      enable_watchpoints_in_psr (ptid);
+    }
 
   return 0;
 }
 
   return 0;
 }
@@ -599,7 +586,6 @@ ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
 static int
 ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
 {
 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;
   int idx;
   long dbr_addr, dbr_mask;
   int max_watchpoints = 4;
@@ -609,43 +595,63 @@ ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
 
   for (idx = 0; idx < max_watchpoints; idx++)
     {
 
   for (idx = 0; idx < max_watchpoints; idx++)
     {
-      fetch_debug_register_pair (ptid, idx, &dbr_addr, &dbr_mask);
+      dbr_addr = debug_registers[2 * idx];
+      dbr_mask = debug_registers[2 * idx + 1];
       if ((dbr_mask & (0x3UL << 62)) && addr == (CORE_ADDR) dbr_addr)
        {
       if ((dbr_mask & (0x3UL << 62)) && addr == (CORE_ADDR) dbr_addr)
        {
+         struct lwp_info *lp;
+         ptid_t ptid;
+
+         debug_registers[2 * idx] = 0;
+         debug_registers[2 * idx + 1] = 0;
          dbr_addr = 0;
          dbr_mask = 0;
          dbr_addr = 0;
          dbr_mask = 0;
-         store_debug_register_pair (ptid, idx, &dbr_addr, &dbr_mask);
+
+         ALL_LWPS (lp, ptid)
+           store_debug_register_pair (ptid, idx, &dbr_addr, &dbr_mask);
+
          return 0;
        }
     }
   return -1;
 }
 
          return 0;
        }
     }
   return -1;
 }
 
+static void
+ia64_linux_new_thread (ptid_t ptid)
+{
+  int i, any;
+
+  any = 0;
+  for (i = 0; i < 8; i++)
+    {
+      if (debug_registers[i] != 0)
+       any = 1;
+      store_debug_register (ptid, i, debug_registers[i]);
+    }
+
+  if (any)
+    enable_watchpoints_in_psr (ptid);
+}
+
 static int
 ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
 {
   CORE_ADDR psr;
 static int
 ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
 {
   CORE_ADDR psr;
-  int tid;
-  struct siginfo siginfo;
-  ptid_t ptid = inferior_ptid;
+  struct siginfo *siginfo_p;
+  struct regcache *regcache = get_current_regcache ();
 
 
-  tid = TIDGET(ptid);
-  if (tid == 0)
-    tid = PIDGET (ptid);
-  
-  errno = 0;
-  ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, &siginfo);
+  siginfo_p = linux_nat_get_siginfo (inferior_ptid);
 
 
-  if (errno != 0 || siginfo.si_signo != SIGTRAP || 
-      (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
+  if (siginfo_p->si_signo != SIGTRAP
+      || (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
     return 0;
 
     return 0;
 
-  psr = read_register_pid (IA64_PSR_REGNUM, ptid);
+  regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr);
   psr |= IA64_PSR_DD;  /* Set the dd bit - this will disable the watchpoint
                            for the next instruction */
   psr |= IA64_PSR_DD;  /* Set the dd bit - this will disable the watchpoint
                            for the next instruction */
-  write_register_pid (IA64_PSR_REGNUM, psr, ptid);
+  regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr);
 
 
-  *addr_p = (CORE_ADDR)siginfo.si_addr;
+  *addr_p = (CORE_ADDR)siginfo_p->si_addr;
   return 1;
 }
 
   return 1;
 }
 
@@ -668,12 +674,13 @@ ia64_linux_can_use_hw_breakpoint (int type, int cnt, int othertype)
 static void
 ia64_linux_fetch_register (struct regcache *regcache, int regnum)
 {
 static void
 ia64_linux_fetch_register (struct regcache *regcache, int regnum)
 {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
   CORE_ADDR addr;
   size_t size;
   PTRACE_TYPE_RET *buf;
   int pid, i;
 
   CORE_ADDR addr;
   size_t size;
   PTRACE_TYPE_RET *buf;
   int pid, i;
 
-  if (ia64_cannot_fetch_register (regnum))
+  if (ia64_cannot_fetch_register (gdbarch, regnum))
     {
       regcache_raw_supply (regcache, regnum, NULL);
       return;
     {
       regcache_raw_supply (regcache, regnum, NULL);
       return;
@@ -686,8 +693,8 @@ ia64_linux_fetch_register (struct regcache *regcache, int regnum)
     pid = ptid_get_pid (inferior_ptid);
 
   /* This isn't really an address, but ptrace thinks of it as one.  */
     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);
+  addr = ia64_register_addr (gdbarch, regnum);
+  size = register_size (gdbarch, regnum);
 
   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
   buf = alloca (size);
 
   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
   buf = alloca (size);
@@ -699,7 +706,8 @@ ia64_linux_fetch_register (struct regcache *regcache, int regnum)
       buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)addr, 0);
       if (errno != 0)
        error (_("Couldn't read register %s (#%d): %s."),
       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));
+              gdbarch_register_name (gdbarch, regnum),
+              regnum, safe_strerror (errno));
 
       addr += sizeof (PTRACE_TYPE_RET);
     }
 
       addr += sizeof (PTRACE_TYPE_RET);
     }
@@ -713,7 +721,9 @@ static void
 ia64_linux_fetch_registers (struct regcache *regcache, int regnum)
 {
   if (regnum == -1)
 ia64_linux_fetch_registers (struct regcache *regcache, int regnum)
 {
   if (regnum == -1)
-    for (regnum = 0; regnum < NUM_REGS; regnum++)
+    for (regnum = 0;
+        regnum < gdbarch_num_regs (get_regcache_arch (regcache));
+        regnum++)
       ia64_linux_fetch_register (regcache, regnum);
   else
     ia64_linux_fetch_register (regcache, regnum);
       ia64_linux_fetch_register (regcache, regnum);
   else
     ia64_linux_fetch_register (regcache, regnum);
@@ -724,12 +734,13 @@ ia64_linux_fetch_registers (struct regcache *regcache, int regnum)
 static void
 ia64_linux_store_register (const struct regcache *regcache, int regnum)
 {
 static void
 ia64_linux_store_register (const struct regcache *regcache, int regnum)
 {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
   CORE_ADDR addr;
   size_t size;
   PTRACE_TYPE_RET *buf;
   int pid, i;
 
   CORE_ADDR addr;
   size_t size;
   PTRACE_TYPE_RET *buf;
   int pid, i;
 
-  if (ia64_cannot_store_register (regnum))
+  if (ia64_cannot_store_register (gdbarch, regnum))
     return;
 
   /* Cater for systems like GNU/Linux, that implement threads as
     return;
 
   /* Cater for systems like GNU/Linux, that implement threads as
@@ -739,8 +750,8 @@ ia64_linux_store_register (const struct regcache *regcache, int regnum)
     pid = ptid_get_pid (inferior_ptid);
 
   /* This isn't really an address, but ptrace thinks of it as one.  */
     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);
+  addr = ia64_register_addr (gdbarch, regnum);
+  size = register_size (gdbarch, regnum);
 
   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
   buf = alloca (size);
 
   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
   buf = alloca (size);
@@ -753,7 +764,8 @@ ia64_linux_store_register (const struct regcache *regcache, int regnum)
       ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)addr, buf[i]);
       if (errno != 0)
        error (_("Couldn't write register %s (#%d): %s."),
       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));
+              gdbarch_register_name (gdbarch, regnum),
+              regnum, safe_strerror (errno));
 
       addr += sizeof (PTRACE_TYPE_RET);
     }
 
       addr += sizeof (PTRACE_TYPE_RET);
     }
@@ -766,7 +778,9 @@ static void
 ia64_linux_store_registers (struct regcache *regcache, int regnum)
 {
   if (regnum == -1)
 ia64_linux_store_registers (struct regcache *regcache, int regnum)
 {
   if (regnum == -1)
-    for (regnum = 0; regnum < NUM_REGS; regnum++)
+    for (regnum = 0;
+        regnum < gdbarch_num_regs (get_regcache_arch (regcache));
+        regnum++)
       ia64_linux_store_register (regcache, regnum);
   else
     ia64_linux_store_register (regcache, regnum);
       ia64_linux_store_register (regcache, regnum);
   else
     ia64_linux_store_register (regcache, regnum);
@@ -796,7 +810,7 @@ void _initialize_ia64_linux_nat (void);
 void
 _initialize_ia64_linux_nat (void)
 {
 void
 _initialize_ia64_linux_nat (void)
 {
-  struct target_ops *t = linux_target ();
+  struct target_ops *t;
 
   /* Fill in the generic GNU/Linux methods.  */
   t = linux_target ();
 
   /* Fill in the generic GNU/Linux methods.  */
   t = linux_target ();
@@ -829,4 +843,5 @@ _initialize_ia64_linux_nat (void)
 
   /* Register the target.  */
   linux_nat_add_target (t);
 
   /* Register the target.  */
   linux_nat_add_target (t);
+  linux_nat_set_new_thread (t, ia64_linux_new_thread);
 }
 }
This page took 0.027462 seconds and 4 git commands to generate.