X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fspu-linux-nat.c;h=c2d6569ee0391b871e92e926932b7adab2b7b815;hb=3e68067fb2d59ea93ea95d713a6c27b635332912;hp=e9b155bbb73d44ff567d85aee5def7dc350b871c;hpb=ecd75fc8eed3bde86036141228074a20e55dcfc9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/spu-linux-nat.c b/gdb/spu-linux-nat.c index e9b155bbb7..c2d6569ee0 100644 --- a/gdb/spu-linux-nat.c +++ b/gdb/spu-linux-nat.c @@ -1,5 +1,5 @@ /* SPU native-dependent code for GDB, the GNU debugger. - Copyright (C) 2006-2014 Free Software Foundation, Inc. + Copyright (C) 2006-2018 Free Software Foundation, Inc. Contributed by Ulrich Weigand . @@ -20,7 +20,6 @@ #include "defs.h" #include "gdbcore.h" -#include #include "target.h" #include "inferior.h" #include "inf-child.h" @@ -31,7 +30,7 @@ #include "gdbthread.h" #include "gdb_bfd.h" -#include +#include "nat/gdb_ptrace.h" #include #include @@ -41,6 +40,28 @@ #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 @@ -48,9 +69,9 @@ fetch_ppc_register (int regno) { PTRACE_TYPE_RET res; - int tid = ptid_get_lwp (inferior_ptid); + int tid = inferior_ptid.lwp (); if (tid == 0) - tid = ptid_get_pid (inferior_ptid); + tid = inferior_ptid.pid (); #ifndef __powerpc64__ /* If running as a 32-bit process on a 64-bit system, we attempt @@ -133,9 +154,9 @@ fetch_ppc_memory (ULONGEST memaddr, gdb_byte *myaddr, int len) / sizeof (PTRACE_TYPE_RET)); PTRACE_TYPE_RET *buffer; - int tid = ptid_get_lwp (inferior_ptid); + int tid = inferior_ptid.lwp (); if (tid == 0) - tid = ptid_get_pid (inferior_ptid); + tid = inferior_ptid.pid (); buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET)); for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET)) @@ -163,9 +184,9 @@ store_ppc_memory (ULONGEST memaddr, const gdb_byte *myaddr, int len) / sizeof (PTRACE_TYPE_RET)); PTRACE_TYPE_RET *buffer; - int tid = ptid_get_lwp (inferior_ptid); + int tid = inferior_ptid.lwp (); if (tid == 0) - tid = ptid_get_pid (inferior_ptid); + tid = inferior_ptid.pid (); buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET)); @@ -226,31 +247,33 @@ parse_spufs_run (int *fd, ULONGEST *addr) } -/* Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF, +/* Implement the to_xfer_partial target_ops method for TARGET_OBJECT_SPU. + Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF, using the /proc file system. */ -static LONGEST + +static enum target_xfer_status spu_proc_xfer_spu (const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, LONGEST len) + ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { char buf[128]; int fd = 0; int ret = -1; - int pid = ptid_get_pid (inferior_ptid); + int pid = inferior_ptid.pid (); if (!annex) - return 0; + return TARGET_XFER_EOF; xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex); fd = open (buf, writebuf? O_WRONLY : O_RDONLY); if (fd <= 0) - return -1; + return TARGET_XFER_E_IO; if (offset != 0 && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset) { close (fd); - return 0; + return TARGET_XFER_EOF; } if (writebuf) @@ -259,7 +282,15 @@ spu_proc_xfer_spu (const char *annex, gdb_byte *readbuf, ret = read (fd, readbuf, (size_t) len); close (fd); - return ret; + if (ret < 0) + return TARGET_XFER_E_IO; + else if (ret == 0) + return TARGET_XFER_EOF; + else + { + *xfered_len = (ULONGEST) ret; + return TARGET_XFER_OK; + } } @@ -287,7 +318,7 @@ spu_bfd_iovec_pread (struct bfd *abfd, void *stream, void *buf, { ULONGEST addr = *(ULONGEST *)stream; - if (fetch_ppc_memory (addr + offset, buf, nbytes) != 0) + if (fetch_ppc_memory (addr + offset, (gdb_byte *)buf, nbytes) != 0) { bfd_set_error (bfd_error_invalid_operation); return -1; @@ -304,41 +335,40 @@ spu_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb) table to find the extent of the last section but that seems pointless when the size is needed only for checks of other parsed values in dbxread.c. */ + memset (sb, 0, sizeof (struct stat)); sb->st_size = INT_MAX; return 0; } -static bfd * +static gdb_bfd_ref_ptr spu_bfd_open (ULONGEST addr) { - struct bfd *nbfd; asection *spu_name; - ULONGEST *open_closure = xmalloc (sizeof (ULONGEST)); + ULONGEST *open_closure = XNEW (ULONGEST); *open_closure = addr; - nbfd = gdb_bfd_openr_iovec ("", "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 ("", "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 = alloca (sect_size - 20 + 1); - bfd_get_section_contents (nbfd, spu_name, buf, 20, sect_size - 20); + char *buf = (char *)alloca (sect_size - 20 + 1); + bfd_get_section_contents (nbfd.get (), spu_name, buf, 20, + sect_size - 20); buf[sect_size - 20] = '\0'; xfree ((char *)nbfd->filename); @@ -357,46 +387,44 @@ static void spu_symbol_file_add_from_memory (int inferior_fd) { ULONGEST addr; - struct bfd *nbfd; - char id[128]; + gdb_byte id[128]; char annex[32]; - int len; + ULONGEST len; + enum target_xfer_status status; /* Read object ID. */ xsnprintf (annex, sizeof annex, "%d/object-id", inferior_fd); - len = spu_proc_xfer_spu (annex, id, NULL, 0, sizeof id); - if (len <= 0 || len >= sizeof id) + status = spu_proc_xfer_spu (annex, id, NULL, 0, sizeof id, &len); + if (status != TARGET_XFER_OK || len >= sizeof id) return; id[len] = 0; - addr = strtoulst (id, NULL, 16); + addr = strtoulst ((const char *) id, NULL, 16); if (!addr) 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, SYMFILE_VERBOSE | SYMFILE_MAINLINE, + 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 (ptid_t ptid) +void +spu_linux_nat_target::post_startup_inferior (ptid_t ptid) { int fd; ULONGEST addr; - int tid = ptid_get_lwp (ptid); + int tid = ptid.lwp (); if (tid == 0) - tid = ptid_get_pid (ptid); + tid = ptid.pid (); while (!parse_spufs_run (&fd, &addr)) { @@ -407,8 +435,8 @@ spu_child_post_startup_inferior (ptid_t ptid) /* 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 (int pid) +void +spu_linux_nat_target::post_attach (int pid) { int fd; ULONGEST addr; @@ -430,9 +458,9 @@ spu_child_post_attach (int pid) /* 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; @@ -443,17 +471,17 @@ spu_child_wait (struct target_ops *ops, set_sigint_trap (); /* Causes SIGINT to be passed on to the attached process. */ - pid = waitpid (ptid_get_pid (ptid), &status, 0); + pid = waitpid (ptid.pid (), &status, 0); if (pid == -1 && errno == ECHILD) /* Try again with __WCLONE to check cloned processes. */ - pid = waitpid (ptid_get_pid (ptid), &status, __WCLONE); + pid = waitpid (ptid.pid (), &status, __WCLONE); save_errno = errno; /* Make sure we don't report an event for the exit of the original program, if we've detached from it. */ if (pid != -1 && !WIFSTOPPED (status) - && pid != ptid_get_pid (inferior_ptid)) + && pid != inferior_ptid.pid ()) { pid = -1; save_errno = EINTR; @@ -475,17 +503,21 @@ spu_child_wait (struct target_ops *ops, } store_waitstatus (ourstatus, status); - return pid_to_ptid (pid); + return ptid_t (pid); } /* 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; @@ -493,11 +525,11 @@ spu_fetch_inferior_registers (struct target_ops *ops, /* 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. */ @@ -505,7 +537,7 @@ spu_fetch_inferior_registers (struct target_ops *ops, { 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. */ @@ -514,22 +546,29 @@ spu_fetch_inferior_registers (struct target_ops *ops, gdb_byte buf[16 * SPU_NUM_GPRS]; char annex[32]; int i; + ULONGEST len; xsnprintf (annex, sizeof annex, "%d/regs", fd); - if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf) + if ((spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf, &len) + == 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; @@ -538,7 +577,7 @@ spu_store_inferior_registers (struct target_ops *ops, 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); } @@ -548,24 +587,26 @@ spu_store_inferior_registers (struct target_ops *ops, gdb_byte buf[16 * SPU_NUM_GPRS]; char annex[32]; int i; + 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); + spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf, &len); } } /* Override the to_xfer_partial routine. */ -static LONGEST -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) +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); + return spu_proc_xfer_spu (annex, readbuf, writebuf, offset, len, + xfered_len); if (object == TARGET_OBJECT_MEMORY) { @@ -574,16 +615,17 @@ spu_xfer_partial (struct target_ops *ops, char mem_annex[32], lslr_annex[32]; gdb_byte buf[32]; ULONGEST lslr; - LONGEST ret; + enum target_xfer_status ret; /* We must be stopped on a spu_run system call. */ if (!parse_spufs_run (&fd, &addr)) - return 0; + return TARGET_XFER_EOF; /* Use the "mem" spufs file to access SPU local store. */ xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd); - ret = spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len); - if (ret > 0) + ret = spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len, + xfered_len); + if (ret == TARGET_XFER_OK) return ret; /* SPU local store access wraps the address around at the @@ -592,42 +634,29 @@ spu_xfer_partial (struct target_ops *ops, trying the original address first, and getting end-of-file. */ xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd); memset (buf, 0, sizeof buf); - if (spu_proc_xfer_spu (lslr_annex, buf, NULL, 0, sizeof buf) <= 0) + if (spu_proc_xfer_spu (lslr_annex, buf, NULL, 0, sizeof buf, xfered_len) + != TARGET_XFER_OK) return ret; - lslr = strtoulst (buf, NULL, 16); + lslr = strtoulst ((const char *) buf, NULL, 16); return spu_proc_xfer_spu (mem_annex, readbuf, writebuf, - offset & lslr, len); + offset & lslr, len, xfered_len); } - return -1; + return TARGET_XFER_E_IO; } /* Override the to_can_use_hw_breakpoint routine. */ -static int -spu_can_use_hw_breakpoint (int type, int cnt, int othertype) +int +spu_linux_nat_target::can_use_hw_breakpoint (enum bptype type, + int cnt, int othertype) { return 0; } - /* 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); }