/* SPU native-dependent code for GDB, the GNU debugger.
- Copyright (C) 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006-2018 Free Software Foundation, Inc.
Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
#define INSTR_SC 0x44000002
#define NR_spu_run 0x0116
+class spu_linux_nat_target final : public inf_ptrace_target
+{
+public:
+ void fetch_registers (struct regcache *regcache, int regnum) override;
+ void store_registers (struct regcache *regcache, int regnum) override;
+
+ void post_attach (int) override;
+ void post_startup_inferior (ptid_t) override;
+
+ ptid_t wait (ptid_t, struct target_waitstatus *, int options) override;
+
+ enum target_xfer_status xfer_partial (enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len) override;
+
+ int can_use_hw_breakpoint (enum bptype, int, int) override;
+};
+
+static spu_linux_nat_target the_spu_linux_nat_target;
/* Fetch PPU register REGNO. */
static ULONGEST
return 0;
}
-static bfd *
+static gdb_bfd_ref_ptr
spu_bfd_open (ULONGEST addr)
{
- struct bfd *nbfd;
asection *spu_name;
ULONGEST *open_closure = XNEW (ULONGEST);
*open_closure = addr;
- nbfd = gdb_bfd_openr_iovec ("<in-memory>", "elf32-spu",
- spu_bfd_iovec_open, open_closure,
- spu_bfd_iovec_pread, spu_bfd_iovec_close,
- spu_bfd_iovec_stat);
- if (!nbfd)
+ gdb_bfd_ref_ptr nbfd (gdb_bfd_openr_iovec ("<in-memory>", "elf32-spu",
+ spu_bfd_iovec_open, open_closure,
+ spu_bfd_iovec_pread,
+ spu_bfd_iovec_close,
+ spu_bfd_iovec_stat));
+ if (nbfd == NULL)
return NULL;
- if (!bfd_check_format (nbfd, bfd_object))
- {
- gdb_bfd_unref (nbfd);
- return NULL;
- }
+ if (!bfd_check_format (nbfd.get (), bfd_object))
+ return NULL;
/* Retrieve SPU name note and update BFD name. */
- spu_name = bfd_get_section_by_name (nbfd, ".note.spu_name");
+ spu_name = bfd_get_section_by_name (nbfd.get (), ".note.spu_name");
if (spu_name)
{
- int sect_size = bfd_section_size (nbfd, spu_name);
+ int sect_size = bfd_section_size (nbfd.get (), spu_name);
if (sect_size > 20)
{
char *buf = (char *)alloca (sect_size - 20 + 1);
- bfd_get_section_contents (nbfd, spu_name, buf, 20, sect_size - 20);
+ bfd_get_section_contents (nbfd.get (), spu_name, buf, 20,
+ sect_size - 20);
buf[sect_size - 20] = '\0';
xfree ((char *)nbfd->filename);
spu_symbol_file_add_from_memory (int inferior_fd)
{
ULONGEST addr;
- struct bfd *nbfd;
gdb_byte id[128];
char annex[32];
return;
/* Open BFD representing SPE executable and read its symbols. */
- nbfd = spu_bfd_open (addr);
- if (nbfd)
+ gdb_bfd_ref_ptr nbfd (spu_bfd_open (addr));
+ if (nbfd != NULL)
{
- struct cleanup *cleanup = make_cleanup_bfd_unref (nbfd);
-
- symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd),
+ symbol_file_add_from_bfd (nbfd.get (), bfd_get_filename (nbfd),
SYMFILE_VERBOSE | SYMFILE_MAINLINE,
NULL, 0, NULL);
- do_cleanups (cleanup);
}
}
/* Override the post_startup_inferior routine to continue running
the inferior until the first spu_run system call. */
-static void
-spu_child_post_startup_inferior (struct target_ops *self, ptid_t ptid)
+void
+spu_linux_nat_target::post_startup_inferior (ptid_t ptid)
{
int fd;
ULONGEST addr;
/* Override the post_attach routine to try load the SPE executable
file image from its copy inside the target process. */
-static void
-spu_child_post_attach (struct target_ops *self, int pid)
+void
+spu_linux_nat_target::post_attach (int pid)
{
int fd;
ULONGEST addr;
/* Wait for child PTID to do something. Return id of the child,
minus_one_ptid in case of error; store status into *OURSTATUS. */
-static ptid_t
-spu_child_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *ourstatus, int options)
+ptid_t
+spu_linux_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
+ int options)
{
int save_errno;
int status;
}
/* Override the fetch_inferior_register routine. */
-static void
-spu_fetch_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
+void
+spu_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
int fd;
ULONGEST addr;
+ /* Since we use functions that rely on inferior_ptid, we need to set and
+ restore it. */
+ scoped_restore save_ptid
+ = make_scoped_restore (&inferior_ptid, regcache->ptid ());
+
/* We must be stopped on a spu_run system call. */
if (!parse_spufs_run (&fd, &addr))
return;
/* The ID register holds the spufs file handle. */
if (regno == -1 || regno == SPU_ID_REGNUM)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[4];
store_unsigned_integer (buf, 4, byte_order, fd);
- regcache_raw_supply (regcache, SPU_ID_REGNUM, buf);
+ regcache->raw_supply (SPU_ID_REGNUM, buf);
}
/* The NPC register is found at ADDR. */
{
gdb_byte buf[4];
if (fetch_ppc_memory (addr, buf, 4) == 0)
- regcache_raw_supply (regcache, SPU_PC_REGNUM, buf);
+ regcache->raw_supply (SPU_PC_REGNUM, buf);
}
/* The GPRs are found in the "regs" spufs file. */
== TARGET_XFER_OK)
&& len == sizeof buf)
for (i = 0; i < SPU_NUM_GPRS; i++)
- regcache_raw_supply (regcache, i, buf + i*16);
+ regcache->raw_supply (i, buf + i*16);
}
}
/* Override the store_inferior_register routine. */
-static void
-spu_store_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
+void
+spu_linux_nat_target::store_registers (struct regcache *regcache, int regno)
{
int fd;
ULONGEST addr;
+ /* Since we use functions that rely on inferior_ptid, we need to set and
+ restore it. */
+ scoped_restore save_ptid
+ = make_scoped_restore (&inferior_ptid, regcache->ptid ());
+
/* We must be stopped on a spu_run system call. */
if (!parse_spufs_run (&fd, &addr))
return;
if (regno == -1 || regno == SPU_PC_REGNUM)
{
gdb_byte buf[4];
- regcache_raw_collect (regcache, SPU_PC_REGNUM, buf);
+ regcache->raw_collect (SPU_PC_REGNUM, buf);
store_ppc_memory (addr, buf, 4);
}
ULONGEST len;
for (i = 0; i < SPU_NUM_GPRS; i++)
- regcache_raw_collect (regcache, i, buf + i*16);
+ regcache->raw_collect (i, buf + i*16);
xsnprintf (annex, sizeof annex, "%d/regs", fd);
spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf, &len);
}
/* Override the to_xfer_partial routine. */
-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, ULONGEST len, ULONGEST *xfered_len)
+enum target_xfer_status
+spu_linux_nat_target::xfer_partial (enum target_object object, const char *annex,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
if (object == TARGET_OBJECT_SPU)
return spu_proc_xfer_spu (annex, readbuf, writebuf, offset, len,
}
/* Override the to_can_use_hw_breakpoint routine. */
-static int
-spu_can_use_hw_breakpoint (struct target_ops *self,
- enum bptype type, int cnt, int othertype)
+int
+spu_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
+ int cnt, int othertype)
{
return 0;
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_spu_nat;
-
/* Initialize SPU native target. */
void
_initialize_spu_nat (void)
{
- /* Generic ptrace methods. */
- struct target_ops *t;
- t = inf_ptrace_target ();
-
- /* Add SPU methods. */
- t->to_post_attach = spu_child_post_attach;
- t->to_post_startup_inferior = spu_child_post_startup_inferior;
- t->to_wait = spu_child_wait;
- t->to_fetch_registers = spu_fetch_inferior_registers;
- t->to_store_registers = spu_store_inferior_registers;
- t->to_xfer_partial = spu_xfer_partial;
- t->to_can_use_hw_breakpoint = spu_can_use_hw_breakpoint;
-
- /* Register SPU target. */
- add_target (t);
+ add_inf_child_target (&the_spu_linux_nat_target);
}