-/* Copyright (C) 2010, 2012 Free Software Foundation, Inc.
+/* Copyright (C) 2010-2014 Free Software Foundation, Inc.
This file is part of GDB.
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
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
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;
(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. */
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. */
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. */
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.
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;
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.
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
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);
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;
}
/* 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;
}
/* 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;