Add target_ops argument to to_insert_hw_breakpoint
[deliverable/binutils-gdb.git] / gdb / ia64-hpux-nat.c
index 4b42c2252f01dbcae27ef0a73be4a14ebae59523..6a4e088c5f0c784507f5eb1a6f5d705b818d4676 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010, 2012 Free Software Foundation, Inc.
+/* Copyright (C) 2010-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -154,12 +154,12 @@ ia64_hpux_wait (struct target_ops *ops, ptid_t ptid,
      process it, and then resume the execution as if the event did
      not happen.  */
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
-      && ourstatus->value.sig == TARGET_SIGNAL_TRAP
+      && ourstatus->value.sig == GDB_SIGNAL_TRAP
       && ia64_hpux_at_dld_breakpoint_p (new_ptid))
     {
       ia64_hpux_handle_dld_breakpoint (new_ptid);
 
-      target_resume (new_ptid, 0, TARGET_SIGNAL_0);
+      target_resume (new_ptid, 0, GDB_SIGNAL_0);
       ourstatus->kind = TARGET_WAITKIND_IGNORE;
     }
 
@@ -337,17 +337,16 @@ ia64_hpux_store_registers (struct target_ops *ops,
    need to be handled manually.  So we override this routine and
    delegate back if we detect that we are not in a special case.  */
 
-static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object,
-                                     const char *, gdb_byte *,
-                                     const gdb_byte *, ULONGEST, LONGEST);
+static target_xfer_partial_ftype *super_xfer_partial;
 
 /* The "xfer_partial" routine for a memory region that is completely
    outside of the backing-store region.  */
 
-static LONGEST
+static enum target_xfer_status
 ia64_hpux_xfer_memory_no_bs (struct target_ops *ops, const char *annex,
                             gdb_byte *readbuf, const gdb_byte *writebuf,
-                            CORE_ADDR addr, LONGEST len)
+                            CORE_ADDR addr, LONGEST len,
+                            ULONGEST *xfered_len)
 {
   /* Memory writes need to be aligned on 16byte boundaries, at least
      when writing in the text section.  On the other hand, the size
@@ -369,17 +368,17 @@ ia64_hpux_xfer_memory_no_bs (struct target_ops *ops, const char *annex,
                                   NULL /* write */,
                                   aligned_addr, addr - aligned_addr);
       if (status <= 0)
-       return 0;
+       return TARGET_XFER_EOF;
       memcpy (aligned_buf + (addr - aligned_addr), writebuf, len);
 
       return super_xfer_partial (ops, TARGET_OBJECT_MEMORY, annex,
                                 NULL /* read */, aligned_buf /* write */,
-                                aligned_addr, aligned_len);
+                                aligned_addr, aligned_len, xfered_len);
     }
   else
     /* Memory read or properly aligned memory write.  */
     return super_xfer_partial (ops, TARGET_OBJECT_MEMORY, annex, readbuf,
-                              writebuf, addr, len);
+                              writebuf, addr, len, xfered_len);
 }
 
 /* Read LEN bytes at ADDR from memory, and store it in BUF.  This memory
@@ -485,13 +484,44 @@ ia64_hpux_xfer_memory_bs (struct target_ops *ops, const char *annex,
     return 0;
 }
 
+/* Get a register value as a unsigned value directly from the system,
+   instead of going through the regcache.
+
+   This function is meant to be used when inferior_ptid is not
+   a thread/process known to GDB.  */
+
+static ULONGEST
+ia64_hpux_get_register_from_save_state_t (int regnum, int reg_size)
+{
+  gdb_byte *buf = alloca (reg_size);
+  int offset = u_offsets[regnum];
+  int status;
+
+  /* The register is assumed to be available for fetching.  */
+  gdb_assert (offset != -1);
+
+  status = ia64_hpux_read_register_from_save_state_t (offset, buf, reg_size);
+  if (status < 0)
+    {
+      /* This really should not happen.  If it does, emit a warning
+        and pretend the register value is zero.  Not exactly the best
+        error recovery mechanism, but better than nothing.  We will
+        try to do better if we can demonstrate that this can happen
+        under normal circumstances.  */
+      warning (_("Failed to read value of register number %d."), regnum);
+      return 0;
+    }
+
+  return extract_unsigned_integer (buf, reg_size, BFD_ENDIAN_BIG);
+}
+
 /* The "xfer_partial" target_ops routine for ia64-hpux, in the case
    where the requested object is TARGET_OBJECT_MEMORY.  */
 
-static LONGEST
+static enum target_xfer_status
 ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex,
                       gdb_byte *readbuf, const gdb_byte *writebuf,
-                      CORE_ADDR addr, LONGEST len)
+                      CORE_ADDR addr, ULONGEST len, ULONGEST *xfered_len)
 {
   CORE_ADDR bsp, bspstore;
   CORE_ADDR start_addr, short_len;
@@ -504,9 +534,24 @@ ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex,
        (3) The region inside the backing-store, which needs to be
            read/written specially.  */
 
-  regcache_raw_read_unsigned (get_current_regcache (), IA64_BSP_REGNUM, &bsp);
-  regcache_raw_read_unsigned (get_current_regcache (), IA64_BSPSTORE_REGNUM,
-                              &bspstore);
+  if (in_inferior_list (ptid_get_pid (inferior_ptid)))
+    {
+      struct regcache *regcache = get_current_regcache ();
+
+      regcache_raw_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
+      regcache_raw_read_unsigned (regcache, IA64_BSPSTORE_REGNUM, &bspstore);
+    }
+  else
+    {
+      /* This is probably a child of our inferior created by a fork.
+        Because this process has not been added to our inferior list
+        (we are probably in the process of handling that child
+        process), we do not have a regcache to read the registers
+        from.  So get those values directly from the kernel.  */
+      bsp = ia64_hpux_get_register_from_save_state_t (IA64_BSP_REGNUM, 8);
+      bspstore =
+       ia64_hpux_get_register_from_save_state_t (IA64_BSPSTORE_REGNUM, 8);
+    }
 
   /* 1. Memory region before BSPSTORE.  */
 
@@ -519,7 +564,7 @@ ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex,
       status = ia64_hpux_xfer_memory_no_bs (ops, annex, readbuf, writebuf,
                                            addr, short_len);
       if (status <= 0)
-        return 0;
+        return TARGET_XFER_EOF;
     }
 
   /* 2. Memory region after BSP.  */
@@ -537,7 +582,7 @@ ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex,
                 writebuf ? writebuf + (start_addr - addr) : NULL,
                 start_addr, short_len);
       if (status <= 0)
-       return 0;
+       return TARGET_XFER_EOF;
     }
 
   /* 3. Memory region between BSPSTORE and BSP.  */
@@ -562,10 +607,11 @@ ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex,
                  writebuf ? writebuf + (start_addr - addr) : NULL,
                  start_addr, short_len);
       if (status < 0)
-       return 0;
+       return TARGET_XFER_EOF;
     }
 
-  return len;
+  *xfered_len = len;
+  return TARGET_XFER_OK;
 }
 
 /* Handle the transfer of TARGET_OBJECT_HPUX_UREGS objects on ia64-hpux.
@@ -575,10 +621,10 @@ ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex,
    we do not currently do not need these transfers), and will raise
    a failed assertion if WRITEBUF is not NULL.  */
 
-static LONGEST
+static enum target_xfer_status
 ia64_hpux_xfer_uregs (struct target_ops *ops, const char *annex,
                      gdb_byte *readbuf, const gdb_byte *writebuf,
-                     ULONGEST offset, LONGEST len)
+                     ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
 {
   int status;
 
@@ -586,8 +632,10 @@ ia64_hpux_xfer_uregs (struct target_ops *ops, const char *annex,
 
   status = ia64_hpux_read_register_from_save_state_t (offset, readbuf, len);
   if (status < 0)
-    return -1;
-  return len;
+    return TARGET_XFER_E_IO;
+
+  *xfered_len = (ULONGEST) len;
+  return TARGET_XFER_OK;
 }
 
 /* Handle the transfer of TARGET_OBJECT_HPUX_SOLIB_GOT objects on ia64-hpux.
@@ -596,10 +644,10 @@ ia64_hpux_xfer_uregs (struct target_ops *ops, const char *annex,
    we do not currently do not need these transfers), and will raise
    a failed assertion if WRITEBUF is not NULL.  */
 
-static LONGEST
+static enum target_xfer_status
 ia64_hpux_xfer_solib_got (struct target_ops *ops, const char *annex,
                          gdb_byte *readbuf, const gdb_byte *writebuf,
-                         ULONGEST offset, LONGEST len)
+                         ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
 {
   CORE_ADDR fun_addr;
   /* The linkage pointer.  We use a uint64_t to make sure that the size
@@ -612,7 +660,7 @@ ia64_hpux_xfer_solib_got (struct target_ops *ops, const char *annex,
   gdb_assert (writebuf == NULL);
 
   if (offset > sizeof (got))
-    return 0;
+    return TARGET_XFER_EOF;
 
   fun_addr = string_to_core_addr (annex);
   got = ia64_hpux_get_solib_linkage_addr (fun_addr);
@@ -621,28 +669,32 @@ ia64_hpux_xfer_solib_got (struct target_ops *ops, const char *annex,
     len = sizeof (got) - offset;
   memcpy (readbuf, &got + offset, len);
 
-  return len;
+  *xfered_len = (ULONGEST) len;
+  return TARGET_XFER_OK;
 }
 
 /* The "to_xfer_partial" target_ops routine for ia64-hpux.  */
 
-static LONGEST
+static enum target_xfer_status
 ia64_hpux_xfer_partial (struct target_ops *ops, enum target_object object,
                        const char *annex, gdb_byte *readbuf,
-                       const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+                       const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+                       ULONGEST *xfered_len)
 {
-  LONGEST val;
+  enum target_xfer_status val;
 
   if (object == TARGET_OBJECT_MEMORY)
-    val = ia64_hpux_xfer_memory (ops, annex, readbuf, writebuf, offset, len);
+    val = ia64_hpux_xfer_memory (ops, annex, readbuf, writebuf, offset, len,
+                                xfered_len);
   else if (object == TARGET_OBJECT_HPUX_UREGS)
-    val = ia64_hpux_xfer_uregs (ops, annex, readbuf, writebuf, offset, len);
+    val = ia64_hpux_xfer_uregs (ops, annex, readbuf, writebuf, offset, len,
+                               xfered_len);
   else if (object == TARGET_OBJECT_HPUX_SOLIB_GOT)
     val = ia64_hpux_xfer_solib_got (ops, annex, readbuf, writebuf, offset,
-                                   len);
+                                   len, xfered_len);
   else
     val = super_xfer_partial (ops, object, annex, readbuf, writebuf, offset,
-                             len);
+                             len, xfered_len);
 
   return val;
 }
@@ -650,7 +702,8 @@ ia64_hpux_xfer_partial (struct target_ops *ops, enum target_object object,
 /* The "to_can_use_hw_breakpoint" target_ops routine for ia64-hpux.  */
 
 static int
-ia64_hpux_can_use_hw_breakpoint (int type, int cnt, int othertype)
+ia64_hpux_can_use_hw_breakpoint (struct target_ops *self,
+                                int type, int cnt, int othertype)
 {
   /* No hardware watchpoint/breakpoint support yet.  */
   return 0;
@@ -679,10 +732,10 @@ ia64_hpux_mourn_inferior (struct target_ops *ops)
 }
 
 /* Prevent warning from -Wmissing-prototypes.  */
-void _initialize_hppa_hpux_nat (void);
+void _initialize_ia64_hpux_nat (void);
 
 void
-_initialize_hppa_hpux_nat (void)
+_initialize_ia64_hpux_nat (void)
 {
   struct target_ops *t;
 
This page took 0.042876 seconds and 4 git commands to generate.