/* Low level interface to SPUs, for the remote server for GDB.
- Copyright (C) 2006-2015 Free Software Foundation, Inc.
+ Copyright (C) 2006-2019 Free Software Foundation, Inc.
Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
#include "server.h"
-#include "gdb_wait.h"
+#include "gdbsupport/gdb_wait.h"
#include <sys/ptrace.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
-#include "filestuff.h"
+#include "gdbsupport/filestuff.h"
#include "hostio.h"
+#include "nat/fork-inferior.h"
/* Some older glibc versions do not define this. */
#ifndef __WNOTHREAD
void init_registers_spu (void);
extern const struct target_desc *tdesc_spu;
+/* Software breakpoint instruction. */
+static const gdb_byte breakpoint[] = { 0x00, 0x00, 0x3f, 0xff };
+
/* Fetch PPU register REGNO. */
static CORE_ADDR
fetch_ppc_register (int regno)
{
PTRACE_TYPE_RET res;
- int tid = ptid_get_lwp (current_ptid);
+ int tid = current_ptid.lwp ();
#ifndef __powerpc64__
/* If running as a 32-bit process on a 64-bit system, we attempt
char buf[8];
errno = 0;
- ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
+ ptrace ((PTRACE_TYPE_ARG1) PPC_PTRACE_PEEKUSR_3264, tid,
(PTRACE_TYPE_ARG3) (regno * 8), buf);
if (errno == 0)
- ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
+ ptrace ((PTRACE_TYPE_ARG1) PPC_PTRACE_PEEKUSR_3264, tid,
(PTRACE_TYPE_ARG3) (regno * 8 + 4), buf + 4);
if (errno == 0)
return (CORE_ADDR) *(unsigned long long *)buf;
if (memaddr >> 32)
{
unsigned long long addr_8 = (unsigned long long) memaddr;
- ptrace (PPC_PTRACE_PEEKTEXT_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
+ ptrace ((PTRACE_TYPE_ARG1) PPC_PTRACE_PEEKTEXT_3264, tid,
+ (PTRACE_TYPE_ARG3) &addr_8, word);
}
else
#endif
if (memaddr >> 32)
{
unsigned long long addr_8 = (unsigned long long) memaddr;
- ptrace (PPC_PTRACE_POKEDATA_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
+ ptrace ((PTRACE_TYPE_ARG1) PPC_PTRACE_POKEDATA_3264, tid,
+ (PTRACE_TYPE_ARG3) &addr_8, word);
}
else
#endif
/ sizeof (PTRACE_TYPE_RET));
PTRACE_TYPE_RET *buffer;
- int tid = ptid_get_lwp (current_ptid);
+ int tid = current_ptid.lwp ();
- buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
+ buffer = XALLOCAVEC (PTRACE_TYPE_RET, count);
for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[i])) != 0)
return ret;
/ sizeof (PTRACE_TYPE_RET));
PTRACE_TYPE_RET *buffer;
- int tid = ptid_get_lwp (current_ptid);
+ int tid = current_ptid.lwp ();
- buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
+ buffer = XALLOCAVEC (PTRACE_TYPE_RET, count);
if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET))
if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[0])) != 0)
if (!annex)
return 0;
- sprintf (buf, "/proc/%ld/fd/%s", ptid_get_lwp (current_ptid), annex);
+ sprintf (buf, "/proc/%ld/fd/%s", current_ptid.lwp (), annex);
fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
if (fd <= 0)
return -1;
return ret;
}
+/* Callback to be used when calling fork_inferior, responsible for
+ actually initiating the tracing of the inferior. */
+
+static void
+spu_ptrace_fun ()
+{
+ if (ptrace (PTRACE_TRACEME, 0, 0, 0) < 0)
+ trace_start_error_with_name ("ptrace");
+ if (setpgid (0, 0) < 0)
+ trace_start_error_with_name ("setpgid");
+}
/* Start an inferior process and returns its pid.
- ALLARGS is a vector of program-name and args. */
+ PROGRAM is the name of the program to be started, and PROGRAM_ARGS
+ are its arguments. */
+
static int
-spu_create_inferior (char *program, char **allargs)
+spu_create_inferior (const char *program,
+ const std::vector<char *> &program_args)
{
int pid;
ptid_t ptid;
struct process_info *proc;
+ std::string str_program_args = stringify_argv (program_args);
- pid = fork ();
- if (pid < 0)
- perror_with_name ("fork");
+ pid = fork_inferior (program,
+ str_program_args.c_str (),
+ get_environ ()->envp (), spu_ptrace_fun,
+ NULL, NULL, NULL, NULL);
- 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);
- }
+ post_fork_inferior (pid, program);
proc = add_process (pid, 0);
proc->tdesc = tdesc_spu;
- ptid = ptid_build (pid, pid, 0);
+ ptid = ptid_t (pid, pid, 0);
add_thread (ptid, NULL);
return pid;
}
proc = add_process (pid, 1);
proc->tdesc = tdesc_spu;
- ptid = ptid_build (pid, pid, 0);
+ ptid = ptid_t (pid, pid, 0);
add_thread (ptid, NULL);
return 0;
}
/* Kill the inferior process. */
static int
-spu_kill (int pid)
+spu_kill (process_info *process)
{
int status, ret;
- struct process_info *process = find_process_pid (pid);
- if (process == NULL)
- return -1;
+ int pid = process->pid;
ptrace (PTRACE_KILL, pid, 0, 0);
/* Detach from inferior process. */
static int
-spu_detach (int pid)
+spu_detach (process_info *process)
{
- struct process_info *process = find_process_pid (pid);
- if (process == NULL)
- return -1;
-
- ptrace (PTRACE_DETACH, pid, 0, 0);
+ ptrace (PTRACE_DETACH, process->pid, 0, 0);
clear_inferiors ();
remove_process (process);
static int
spu_thread_alive (ptid_t ptid)
{
- return ptid_equal (ptid, current_ptid);
+ return ptid == current_ptid;
}
/* Resume process. */
static void
spu_resume (struct thread_resume *resume_info, size_t n)
{
+ struct thread_info *thr = get_first_thread ();
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))
+ if (resume_info[i].thread == minus_one_ptid
+ || resume_info[i].thread == ptid_of (thr))
break;
if (i == n)
regcache_invalidate ();
errno = 0;
- ptrace (PTRACE_CONT, ptid_get_lwp (current_ptid), 0, resume_info[i].sig);
+ ptrace (PTRACE_CONT, ptid_of (thr).lwp (), 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 pid = ptid.pid ();
int w;
int ret;
ourstatus->kind = TARGET_WAITKIND_EXITED;
ourstatus->value.integer = WEXITSTATUS (w);
clear_inferiors ();
- return pid_to_ptid (ret);
+ return ptid_t (ret);
}
else if (!WIFSTOPPED (w))
{
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (w));
clear_inferiors ();
- return pid_to_ptid (ret);
+ return ptid_t (ret);
}
/* After attach, we may have received a SIGSTOP. Do not return this
{
ourstatus->kind = TARGET_WAITKIND_STOPPED;
ourstatus->value.sig = GDB_SIGNAL_0;
- return ptid_build (ret, ret, 0);
+ return ptid_t (ret, ret, 0);
}
ourstatus->kind = TARGET_WAITKIND_STOPPED;
ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (w));
- return ptid_build (ret, ret, 0);
+ return ptid_t (ret, ret, 0);
}
/* Fetch inferior registers. */
static void
spu_request_interrupt (void)
{
- syscall (SYS_tkill, ptid_get_lwp (current_ptid), SIGINT);
+ struct thread_info *thr = get_first_thread ();
+
+ syscall (SYS_tkill, lwpid_of (thr), SIGINT);
+}
+
+/* Implementation of the target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+spu_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = sizeof breakpoint;
+ return breakpoint;
}
static struct target_ops spu_target_ops = {
spu_create_inferior,
- NULL, /* arch_setup */
+ NULL, /* post_create_inferior */
spu_attach,
spu_kill,
spu_detach,
NULL, /* supports_stopped_by_sw_breakpoint */
NULL, /* stopped_by_hw_breakpoint */
NULL, /* supports_stopped_by_hw_breakpoint */
- NULL, /* supports_conditional_breakpoints */
+ NULL, /* supports_hardware_single_step */
NULL,
NULL,
NULL,
NULL,
spu_proc_xfer_spu,
hostio_last_error_from_errno,
+ NULL, /* qxfer_osdata */
+ NULL, /* qxfer_siginfo */
+ NULL, /* supports_non_stop */
+ NULL, /* async */
+ NULL, /* start_non_stop */
+ NULL, /* supports_multi_process */
+ NULL, /* supports_fork_events */
+ NULL, /* supports_vfork_events */
+ NULL, /* supports_exec_events */
+ NULL, /* handle_new_gdb_connection */
+ NULL, /* handle_monitor_command */
+ NULL, /* core_of_thread */
+ NULL, /* read_loadmap */
+ NULL, /* process_qsupported */
+ NULL, /* supports_tracepoints */
+ NULL, /* read_pc */
+ NULL, /* write_pc */
+ NULL, /* thread_stopped */
+ NULL, /* get_tib_address */
+ NULL, /* pause_all */
+ NULL, /* unpause_all */
+ NULL, /* stabilize_threads */
+ NULL, /* install_fast_tracepoint_jump_pad */
+ NULL, /* emit_ops */
+ NULL, /* supports_disable_randomization */
+ NULL, /* get_min_fast_tracepoint_insn_len */
+ NULL, /* qxfer_libraries_svr4 */
+ NULL, /* support_agent */
+ NULL, /* enable_btrace */
+ NULL, /* disable_btrace */
+ NULL, /* read_btrace */
+ NULL, /* read_btrace_conf */
+ NULL, /* supports_range_stepping */
+ NULL, /* pid_to_exec_file */
+ NULL, /* multifs_open */
+ NULL, /* multifs_unlink */
+ NULL, /* multifs_readlink */
+ NULL, /* breakpoint_kind_from_pc */
+ spu_sw_breakpoint_from_kind,
};
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 ();
}