/* Cell SPU GNU/Linux multi-architecture debugging support.
- Copyright (C) 2009-2013 Free Software Foundation, Inc.
+ Copyright (C) 2009-2015 Free Software Foundation, Inc.
Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
#include "defs.h"
#include "gdbcore.h"
#include "gdbcmd.h"
-#include "gdb_string.h"
-#include "gdb_assert.h"
#include "arch-utils.h"
#include "observer.h"
#include "inferior.h"
parse_spufs_run (ptid_t ptid, int *fd, CORE_ADDR *addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+ struct cleanup *old_chain;
struct gdbarch_tdep *tdep;
struct regcache *regcache;
gdb_byte buf[4];
if (gdbarch_bfd_arch_info (target_gdbarch ())->arch != bfd_arch_powerpc)
return 0;
+ /* If we're called too early (e.g. after fork), we cannot
+ access the inferior yet. */
+ if (find_inferior_ptid (ptid) == NULL)
+ return 0;
+
/* Get PPU-side registers. */
regcache = get_thread_arch_regcache (ptid, target_gdbarch ());
tdep = gdbarch_tdep (target_gdbarch ());
/* Fetch instruction preceding current NIP. */
- if (target_read_memory (regcache_read_pc (regcache) - 4, buf, 4) != 0)
+ old_chain = save_inferior_ptid ();
+ inferior_ptid = ptid;
+ regval = target_read_memory (regcache_read_pc (regcache) - 4, buf, 4);
+ do_cleanups (old_chain);
+ if (regval != 0)
return 0;
/* It should be a "sc" instruction. */
if (extract_unsigned_integer (buf, 4, byte_order) != INSTR_SC)
/* Override the to_region_ok_for_hw_watchpoint routine. */
static int
-spu_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
+spu_region_ok_for_hw_watchpoint (struct target_ops *self,
+ CORE_ADDR addr, int len)
{
- struct target_ops *ops_beneath = find_target_beneath (&spu_ops);
- while (ops_beneath && !ops_beneath->to_region_ok_for_hw_watchpoint)
- ops_beneath = find_target_beneath (ops_beneath);
+ struct target_ops *ops_beneath = find_target_beneath (self);
/* We cannot watch SPU local store. */
if (SPUADDR_SPU (addr) != -1)
return 0;
- if (ops_beneath)
- return ops_beneath->to_region_ok_for_hw_watchpoint (addr, len);
-
- return 0;
+ return ops_beneath->to_region_ok_for_hw_watchpoint (ops_beneath, addr, len);
}
/* Override the to_fetch_registers routine. */
/* This version applies only if we're currently in spu_run. */
if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
{
- while (ops_beneath && !ops_beneath->to_fetch_registers)
- ops_beneath = find_target_beneath (ops_beneath);
-
- gdb_assert (ops_beneath);
ops_beneath->to_fetch_registers (ops_beneath, regcache, regno);
return;
}
/* This version applies only if we're currently in spu_run. */
if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
{
- while (ops_beneath && !ops_beneath->to_fetch_registers)
- ops_beneath = find_target_beneath (ops_beneath);
-
- gdb_assert (ops_beneath);
ops_beneath->to_store_registers (ops_beneath, regcache, regno);
return;
}
}
/* Override the to_xfer_partial routine. */
-static LONGEST
+static enum target_xfer_status
spu_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)
{
struct target_ops *ops_beneath = find_target_beneath (ops);
- while (ops_beneath && !ops_beneath->to_xfer_partial)
- ops_beneath = find_target_beneath (ops_beneath);
- gdb_assert (ops_beneath);
/* Use the "mem" spufs file to access SPU local store. */
if (object == TARGET_OBJECT_MEMORY)
char mem_annex[32], lslr_annex[32];
gdb_byte buf[32];
ULONGEST lslr;
- LONGEST ret;
+ enum target_xfer_status ret;
if (fd >= 0)
{
xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
ret = ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
mem_annex, readbuf, writebuf,
- addr, len);
- if (ret > 0)
+ addr, len, xfered_len);
+ if (ret == TARGET_XFER_OK)
return ret;
/* SPU local store access wraps the address around at the
memset (buf, 0, sizeof buf);
if (ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
lslr_annex, buf, NULL,
- 0, sizeof buf) <= 0)
+ 0, sizeof buf, xfered_len)
+ != TARGET_XFER_OK)
return ret;
- lslr = strtoulst (buf, NULL, 16);
+ lslr = strtoulst ((char *) buf, NULL, 16);
return ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
mem_annex, readbuf, writebuf,
- addr & lslr, len);
+ addr & lslr, len, xfered_len);
}
}
return ops_beneath->to_xfer_partial (ops_beneath, object, annex,
- readbuf, writebuf, offset, len);
+ readbuf, writebuf, offset, len, xfered_len);
}
/* Override the to_search_memory routine. */
CORE_ADDR *found_addrp)
{
struct target_ops *ops_beneath = find_target_beneath (ops);
- while (ops_beneath && !ops_beneath->to_search_memory)
- ops_beneath = find_target_beneath (ops_beneath);
- /* For SPU local store, always fall back to the simple method. Likewise
- if we do not have any target-specific special implementation. */
- if (!ops_beneath || SPUADDR_SPU (start_addr) >= 0)
+ /* For SPU local store, always fall back to the simple method. */
+ if (SPUADDR_SPU (start_addr) >= 0)
return simple_search_memory (ops,
start_addr, search_space_len,
pattern, pattern_len, found_addrp);
spu_mourn_inferior (struct target_ops *ops)
{
struct target_ops *ops_beneath = find_target_beneath (ops);
- while (ops_beneath && !ops_beneath->to_mourn_inferior)
- ops_beneath = find_target_beneath (ops_beneath);
- gdb_assert (ops_beneath);
ops_beneath->to_mourn_inferior (ops_beneath);
spu_multiarch_deactivate ();
}
{
/* Install ourselves on the target stack. */
init_spu_ops ();
- add_target (&spu_ops);
+ complete_target_initialization (&spu_ops);
/* Install observers to watch for SPU objects. */
observer_attach_inferior_created (spu_multiarch_inferior_created);