gdb/gdbserver/spu-low.c - gdb
Global variables defined
Functions defined
Macros defined
Source code
- #include "server.h"
- #include "gdb_wait.h"
- #include <sys/ptrace.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/syscall.h>
- #include "filestuff.h"
- #include "hostio.h"
- #ifndef __WNOTHREAD
- #define __WNOTHREAD 0x20000000
- #endif
- #define PTRACE_TYPE_RET long
- #define PTRACE_TYPE_ARG3 long
- #define SPU_NUM_REGS 130
- #define SPU_NUM_CORE_REGS 128
- #define SPU_ID_REGNUM 128
- #define SPU_PC_REGNUM 129
- #define INSTR_SC 0x44000002
- #define NR_spu_run 0x0116
- int using_threads = 0;
- void init_registers_spu (void);
- extern const struct target_desc *tdesc_spu;
- static CORE_ADDR
- fetch_ppc_register (int regno)
- {
- PTRACE_TYPE_RET res;
- int tid = ptid_get_lwp (current_ptid);
- #ifndef __powerpc64__
-
- {
- char buf[8];
- errno = 0;
- ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
- (PTRACE_TYPE_ARG3) (regno * 8), buf);
- if (errno == 0)
- ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
- (PTRACE_TYPE_ARG3) (regno * 8 + 4), buf + 4);
- if (errno == 0)
- return (CORE_ADDR) *(unsigned long long *)buf;
- }
- #endif
- errno = 0;
- res = ptrace (PT_READ_U, tid,
- (PTRACE_TYPE_ARG3) (regno * sizeof (PTRACE_TYPE_RET)), 0);
- if (errno != 0)
- {
- char mess[128];
- sprintf (mess, "reading PPC register #%d", regno);
- perror_with_name (mess);
- }
- return (CORE_ADDR) (unsigned long) res;
- }
- static int
- fetch_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET *word)
- {
- errno = 0;
- #ifndef __powerpc64__
- if (memaddr >> 32)
- {
- unsigned long long addr_8 = (unsigned long long) memaddr;
- ptrace (PPC_PTRACE_PEEKTEXT_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
- }
- else
- #endif
- *word = ptrace (PT_READ_I, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, 0);
- return errno;
- }
- static int
- store_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET word)
- {
- errno = 0;
- #ifndef __powerpc64__
- if (memaddr >> 32)
- {
- unsigned long long addr_8 = (unsigned long long) memaddr;
- ptrace (PPC_PTRACE_POKEDATA_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
- }
- else
- #endif
- ptrace (PT_WRITE_D, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, word);
- return errno;
- }
- static int
- fetch_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
- {
- int i, ret;
- CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
- int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
- / sizeof (PTRACE_TYPE_RET));
- PTRACE_TYPE_RET *buffer;
- int tid = ptid_get_lwp (current_ptid);
- buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
- for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
- if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[i])) != 0)
- return ret;
- memcpy (myaddr,
- (char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
- len);
- return 0;
- }
- static int
- store_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
- {
- int i, ret;
- CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
- int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
- / sizeof (PTRACE_TYPE_RET));
- PTRACE_TYPE_RET *buffer;
- int tid = ptid_get_lwp (current_ptid);
- buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
- if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET))
- if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[0])) != 0)
- return ret;
- if (count > 1)
- if ((ret = fetch_ppc_memory_1 (tid, addr + (count - 1)
- * sizeof (PTRACE_TYPE_RET),
- &buffer[count - 1])) != 0)
- return ret;
- memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
- myaddr, len);
- for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
- if ((ret = store_ppc_memory_1 (tid, addr, buffer[i])) != 0)
- return ret;
- return 0;
- }
- static int
- parse_spufs_run (int *fd, CORE_ADDR *addr)
- {
- unsigned int insn;
- CORE_ADDR pc = fetch_ppc_register (32);
-
- if (fetch_ppc_memory (pc-4, (char *) &insn, 4) != 0)
- return 0;
-
- if (insn != INSTR_SC)
- return 0;
-
- if (fetch_ppc_register (0) != NR_spu_run)
- return 0;
-
- *fd = fetch_ppc_register (34);
- *addr = fetch_ppc_register (4);
- return 1;
- }
- static int
- spu_proc_xfer_spu (const char *annex, unsigned char *readbuf,
- const unsigned char *writebuf,
- CORE_ADDR offset, int len)
- {
- char buf[128];
- int fd = 0;
- int ret = -1;
- if (!annex)
- return 0;
- sprintf (buf, "/proc/%ld/fd/%s", ptid_get_lwp (current_ptid), annex);
- fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
- if (fd <= 0)
- return -1;
- if (offset != 0
- && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
- {
- close (fd);
- return 0;
- }
- if (writebuf)
- ret = write (fd, writebuf, (size_t) len);
- else if (readbuf)
- ret = read (fd, readbuf, (size_t) len);
- close (fd);
- return ret;
- }
- static int
- spu_create_inferior (char *program, char **allargs)
- {
- int pid;
- ptid_t ptid;
- struct process_info *proc;
- pid = fork ();
- if (pid < 0)
- perror_with_name ("fork");
- if (pid == 0)
- {
- close_most_fds ();
- ptrace (PTRACE_TRACEME, 0, 0, 0);
- setpgid (0, 0);
- execv (program, allargs);
- if (errno == ENOENT)
- execvp (program, allargs);
- fprintf (stderr, "Cannot exec %s: %s.\n", program,
- strerror (errno));
- fflush (stderr);
- _exit (0177);
- }
- proc = add_process (pid, 0);
- proc->tdesc = tdesc_spu;
- ptid = ptid_build (pid, pid, 0);
- add_thread (ptid, NULL);
- return pid;
- }
- int
- spu_attach (unsigned long pid)
- {
- ptid_t ptid;
- struct process_info *proc;
- if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
- {
- fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
- strerror (errno), errno);
- fflush (stderr);
- _exit (0177);
- }
- proc = add_process (pid, 1);
- proc->tdesc = tdesc_spu;
- ptid = ptid_build (pid, pid, 0);
- add_thread (ptid, NULL);
- return 0;
- }
- static int
- spu_kill (int pid)
- {
- int status, ret;
- struct process_info *process = find_process_pid (pid);
- if (process == NULL)
- return -1;
- ptrace (PTRACE_KILL, pid, 0, 0);
- do {
- ret = waitpid (pid, &status, 0);
- if (WIFEXITED (status) || WIFSIGNALED (status))
- break;
- } while (ret != -1 || errno != ECHILD);
- clear_inferiors ();
- remove_process (process);
- return 0;
- }
- static int
- spu_detach (int pid)
- {
- struct process_info *process = find_process_pid (pid);
- if (process == NULL)
- return -1;
- ptrace (PTRACE_DETACH, pid, 0, 0);
- clear_inferiors ();
- remove_process (process);
- return 0;
- }
- static void
- spu_mourn (struct process_info *process)
- {
- remove_process (process);
- }
- static void
- spu_join (int pid)
- {
- int status, ret;
- do {
- ret = waitpid (pid, &status, 0);
- if (WIFEXITED (status) || WIFSIGNALED (status))
- break;
- } while (ret != -1 || errno != ECHILD);
- }
- static int
- spu_thread_alive (ptid_t ptid)
- {
- return ptid_equal (ptid, current_ptid);
- }
- static void
- spu_resume (struct thread_resume *resume_info, size_t n)
- {
- size_t i;
- for (i = 0; i < n; i++)
- if (ptid_equal (resume_info[i].thread, minus_one_ptid)
- || ptid_equal (resume_info[i].thread, current_ptid))
- break;
- if (i == n)
- return;
-
- if (resume_info[i].kind == resume_step)
- fprintf (stderr, "Hardware single-step not supported.\n");
- regcache_invalidate ();
- errno = 0;
- ptrace (PTRACE_CONT, ptid_get_lwp (current_ptid), 0, resume_info[i].sig);
- if (errno)
- perror_with_name ("ptrace");
- }
- static ptid_t
- spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
- {
- int pid = ptid_get_pid (ptid);
- int w;
- int ret;
- while (1)
- {
- ret = waitpid (pid, &w, WNOHANG | __WALL | __WNOTHREAD);
- if (ret == -1)
- {
- if (errno != ECHILD)
- perror_with_name ("waitpid");
- }
- else if (ret > 0)
- break;
- usleep (1000);
- }
-
- if (!server_waiting)
- {
- int fd;
- CORE_ADDR addr;
- while (!parse_spufs_run (&fd, &addr))
- {
- ptrace (PT_SYSCALL, pid, (PTRACE_TYPE_ARG3) 0, 0);
- waitpid (pid, NULL, __WALL | __WNOTHREAD);
- }
- }
- if (WIFEXITED (w))
- {
- fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
- ourstatus->kind = TARGET_WAITKIND_EXITED;
- ourstatus->value.integer = WEXITSTATUS (w);
- clear_inferiors ();
- return pid_to_ptid (ret);
- }
- else if (!WIFSTOPPED (w))
- {
- fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
- ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
- ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (w));
- clear_inferiors ();
- return pid_to_ptid (ret);
- }
-
- if (!server_waiting)
- {
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_0;
- return ptid_build (ret, ret, 0);
- }
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (w));
- return ptid_build (ret, ret, 0);
- }
- static void
- spu_fetch_registers (struct regcache *regcache, int regno)
- {
- int fd;
- CORE_ADDR addr;
-
- if (!parse_spufs_run (&fd, &addr))
- return;
-
- if (regno == -1 || regno == SPU_ID_REGNUM)
- supply_register (regcache, SPU_ID_REGNUM, (char *)&fd);
-
- if (regno == -1 || regno == SPU_PC_REGNUM)
- {
- char buf[4];
- if (fetch_ppc_memory (addr, buf, 4) == 0)
- supply_register (regcache, SPU_PC_REGNUM, buf);
- }
-
- if (regno == -1 || (regno >= 0 && regno < SPU_NUM_CORE_REGS))
- {
- unsigned char buf[16*SPU_NUM_CORE_REGS];
- char annex[32];
- int i;
- sprintf (annex, "%d/regs", fd);
- if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf)
- for (i = 0; i < SPU_NUM_CORE_REGS; i++)
- supply_register (regcache, i, buf + i*16);
- }
- }
- static void
- spu_store_registers (struct regcache *regcache, int regno)
- {
- int fd;
- CORE_ADDR addr;
-
- if (regno == 0)
- regno = -1;
-
- if (!parse_spufs_run (&fd, &addr))
- return;
-
- if (regno == -1 || regno == SPU_PC_REGNUM)
- {
- char buf[4];
- collect_register (regcache, SPU_PC_REGNUM, buf);
- store_ppc_memory (addr, buf, 4);
- }
-
- if (regno == -1 || (regno >= 0 && regno < SPU_NUM_CORE_REGS))
- {
- unsigned char buf[16*SPU_NUM_CORE_REGS];
- char annex[32];
- int i;
- for (i = 0; i < SPU_NUM_CORE_REGS; i++)
- collect_register (regcache, i, buf + i*16);
- sprintf (annex, "%d/regs", fd);
- spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf);
- }
- }
- static int
- spu_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
- {
- int fd, ret;
- CORE_ADDR addr;
- char annex[32], lslr_annex[32], buf[32];
- CORE_ADDR lslr;
-
- if (!parse_spufs_run (&fd, &addr))
- return 0;
-
- sprintf (annex, "%d/mem", fd);
- ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr, len);
- if (ret > 0)
- return ret == len ? 0 : EIO;
-
- sprintf (lslr_annex, "%d/lslr", fd);
- memset (buf, 0, sizeof buf);
- if (spu_proc_xfer_spu (lslr_annex, (unsigned char *)buf, NULL,
- 0, sizeof buf) <= 0)
- return ret;
- lslr = strtoul (buf, NULL, 16);
- ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr & lslr, len);
- return ret == len ? 0 : EIO;
- }
- static int
- spu_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
- {
- int fd, ret;
- CORE_ADDR addr;
- char annex[32], lslr_annex[32], buf[32];
- CORE_ADDR lslr;
-
- if (!parse_spufs_run (&fd, &addr))
- return 0;
-
- sprintf (annex, "%d/mem", fd);
- ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr, len);
- if (ret > 0)
- return ret == len ? 0 : EIO;
-
- sprintf (lslr_annex, "%d/lslr", fd);
- memset (buf, 0, sizeof buf);
- if (spu_proc_xfer_spu (lslr_annex, (unsigned char *)buf, NULL,
- 0, sizeof buf) <= 0)
- return ret;
- lslr = strtoul (buf, NULL, 16);
- ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr & lslr, len);
- return ret == len ? 0 : EIO;
- }
- static void
- spu_look_up_symbols (void)
- {
- }
- static void
- spu_request_interrupt (void)
- {
- syscall (SYS_tkill, ptid_get_lwp (current_ptid), SIGINT);
- }
- static struct target_ops spu_target_ops = {
- spu_create_inferior,
- spu_attach,
- spu_kill,
- spu_detach,
- spu_mourn,
- spu_join,
- spu_thread_alive,
- spu_resume,
- spu_wait,
- spu_fetch_registers,
- spu_store_registers,
- NULL,
- NULL,
- spu_read_memory,
- spu_write_memory,
- spu_look_up_symbols,
- spu_request_interrupt,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- spu_proc_xfer_spu,
- hostio_last_error_from_errno,
- };
- void
- initialize_low (void)
- {
- static const unsigned char breakpoint[] = { 0x00, 0x00, 0x3f, 0xff };
- set_target_ops (&spu_target_ops);
- set_breakpoint_data (breakpoint, sizeof breakpoint);
- init_registers_spu ();
- }