-/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
-#include "gdb_wait.h"
+#include "gdbsupport/gdb_wait.h"
#include <signal.h>
-#include "filestuff.h"
+#include "gdbsupport/filestuff.h"
+#include "gdbsupport/common-inferior.h"
+#include "nat/fork-inferior.h"
int using_threads = 1;
/* Build a ptid_t given a PID and a LynxOS TID. */
static ptid_t
-lynx_ptid_build (int pid, long tid)
+lynx_ptid_t (int pid, long tid)
{
/* brobecker/2010-06-21: It looks like the LWP field in ptids
should be distinct for each thread (see write_ptid where it
writes the thread ID from the LWP). So instead of storing
the LynxOS tid in the tid field of the ptid, we store it in
the lwp field. */
- return ptid_build (pid, tid, 0);
+ return ptid_t (pid, tid, 0);
}
/* Return the process ID of the given PTID.
static int
lynx_ptid_get_pid (ptid_t ptid)
{
- return ptid_get_pid (ptid);
+ return ptid.pid ();
}
/* Return the LynxOS tid of the given PTID. */
static long
lynx_ptid_get_tid (ptid_t ptid)
{
- /* See lynx_ptid_build: The LynxOS tid is stored inside the lwp field
+ /* See lynx_ptid_t: The LynxOS tid is stored inside the lwp field
of the ptid. */
- return ptid_get_lwp (ptid);
+ return ptid.lwp ();
}
/* For a given PTID, return the associated PID as known by the LynxOS
proc = add_process (pid, attached);
proc->tdesc = lynx_tdesc;
- proc->priv = xcalloc (1, sizeof (*proc->priv));
+ proc->priv = XCNEW (struct process_info_private);
proc->priv->last_wait_event_ptid = null_ptid;
return proc;
}
+/* Callback used by fork_inferior to start tracing the inferior. */
+
+static void
+lynx_ptrace_fun ()
+{
+ int pgrp;
+
+ /* Switch child to its own process group so that signals won't
+ directly affect GDBserver. */
+ pgrp = getpid();
+ if (pgrp < 0)
+ trace_start_error_with_name ("pgrp");
+ if (setpgid (0, pgrp) < 0)
+ trace_start_error_with_name ("setpgid");
+ if (ioctl (0, TIOCSPGRP, &pgrp) < 0)
+ trace_start_error_with_name ("ioctl");
+ if (lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0) < 0)
+ trace_start_error_with_name ("lynx_ptrace");
+}
+
/* Implement the create_inferior method of the target_ops vector. */
static int
-lynx_create_inferior (char *program, char **allargs)
+lynx_create_inferior (const char *program,
+ const std::vector<char *> &program_args)
{
int pid;
+ std::string str_program_args = stringify_argv (program_args);
lynx_debug ("lynx_create_inferior ()");
- pid = fork ();
- if (pid < 0)
- perror_with_name ("fork");
+ pid = fork_inferior (program,
+ str_program_args.c_str (),
+ get_environ ()->envp (), lynx_ptrace_fun,
+ NULL, NULL, NULL, NULL);
- if (pid == 0)
- {
- int pgrp;
-
- close_most_fds ();
-
- /* Switch child to its own process group so that signals won't
- directly affect gdbserver. */
- pgrp = getpid();
- setpgid (0, pgrp);
- ioctl (0, TIOCSPGRP, &pgrp);
- lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0);
- execv (program, allargs);
- fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror (errno));
- fflush (stderr);
- _exit (0177);
- }
+ post_fork_inferior (pid, program);
lynx_add_process (pid, 0);
/* Do not add the process thread just yet, as we do not know its tid.
if ((sscanf (buf, "%d %d", &thread_pid, &thread_tid) == 2
&& thread_pid == pid))
{
- ptid_t thread_ptid = lynx_ptid_build (pid, thread_tid);
+ ptid_t thread_ptid = lynx_ptid_t (pid, thread_tid);
if (!find_thread_ptid (thread_ptid))
{
static int
lynx_attach (unsigned long pid)
{
- ptid_t ptid = lynx_ptid_build (pid, 0);
+ ptid_t ptid = lynx_ptid_t (pid, 0);
if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0)
error ("Cannot attach to process %lu: %s (%d)\n", pid,
- strerror (errno), errno);
+ safe_strerror (errno), errno);
lynx_add_process (pid, 1);
lynx_add_threads_after_attach (pid);
LynxOS 178 is a little more sensitive, and triggers some
unexpected signals (Eg SIG61) when we resume the inferior
using a different thread. */
- if (ptid_equal (ptid, minus_one_ptid))
+ if (ptid == minus_one_ptid)
ptid = current_process()->priv->last_wait_event_ptid;
/* The ptid might still be minus_one_ptid; this can happen between
the moment we create the inferior or attach to a process, and
the moment we resume its execution for the first time. It is
fine to use the current_thread's ptid in those cases. */
- if (ptid_equal (ptid, minus_one_ptid))
- ptid = thread_to_gdb_id (current_thread);
+ if (ptid == minus_one_ptid)
+ ptid = ptid_of (current_thread);
- regcache_invalidate ();
+ regcache_invalidate_pid (ptid.pid ());
errno = 0;
lynx_ptrace (request, ptid, 1, signal, 0);
int wstat;
ptid_t new_ptid;
- if (ptid_equal (ptid, minus_one_ptid))
- pid = lynx_ptid_get_pid (thread_to_gdb_id (current_thread));
+ if (ptid == minus_one_ptid)
+ pid = lynx_ptid_get_pid (ptid_of (current_thread));
else
pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
retry:
ret = lynx_waitpid (pid, &wstat);
- new_ptid = lynx_ptid_build (ret, ((union wait *) &wstat)->w_tid);
+ new_ptid = lynx_ptid_t (ret, ((union wait *) &wstat)->w_tid);
find_process_pid (ret)->priv->last_wait_event_ptid = new_ptid;
/* If this is a new thread, then add it now. The reason why we do
/* Implement the kill target_ops method. */
static int
-lynx_kill (int pid)
+lynx_kill (process_info *process)
{
- ptid_t ptid = lynx_ptid_build (pid, 0);
+ ptid_t ptid = lynx_ptid_t (process->pid, 0);
struct target_waitstatus status;
- struct process_info *process;
-
- process = find_process_pid (pid);
- if (process == NULL)
- return -1;
lynx_ptrace (PTRACE_KILL, ptid, 0, 0, 0);
lynx_wait (ptid, &status, 0);
/* Implement the detach target_ops method. */
static int
-lynx_detach (int pid)
+lynx_detach (process_info *process)
{
- ptid_t ptid = lynx_ptid_build (pid, 0);
- struct process_info *process;
-
- process = find_process_pid (pid);
- if (process == NULL)
- return -1;
+ ptid_t ptid = lynx_ptid_t (process->pid, 0);
lynx_ptrace (PTRACE_DETACH, ptid, 0, 0, 0);
the_target->mourn (process);
static void
lynx_mourn (struct process_info *proc)
{
+ for_each_thread (proc->pid, remove_thread);
+
/* Free our private data. */
free (proc->priv);
proc->priv = NULL;
- clear_inferiors ();
+ remove_process (proc);
}
/* Implement the join target_ops method. */
lynx_fetch_registers (struct regcache *regcache, int regno)
{
struct lynx_regset_info *regset = lynx_target_regsets;
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
+ ptid_t inferior_ptid = ptid_of (current_thread);
lynx_debug ("lynx_fetch_registers (regno = %d)", regno);
lynx_store_registers (struct regcache *regcache, int regno)
{
struct lynx_regset_info *regset = lynx_target_regsets;
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
+ ptid_t inferior_ptid = ptid_of (current_thread);
lynx_debug ("lynx_store_registers (regno = %d)", regno);
int buf;
const int xfer_size = sizeof (buf);
CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
+ ptid_t inferior_ptid = ptid_of (current_thread);
while (addr < memaddr + len)
{
int buf;
const int xfer_size = sizeof (buf);
CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
+ ptid_t inferior_ptid = ptid_of (current_thread);
while (addr < memaddr + len)
{
static void
lynx_request_interrupt (void)
{
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
+ ptid_t inferior_ptid = ptid_of (get_first_thread ());
kill (lynx_ptid_get_pid (inferior_ptid), SIGINT);
}
/* The LynxOS target_ops vector. */
-static struct target_ops lynx_target_ops = {
+static process_stratum_target lynx_target_ops = {
lynx_create_inferior,
+ NULL, /* post_create_inferior */
lynx_attach,
lynx_kill,
lynx_detach,
NULL, /* supports_stopped_by_sw_breakpoint */
NULL, /* stopped_by_hw_breakpoint */
NULL, /* supports_stopped_by_hw_breakpoint */
- /* Although lynx has hardware single step, still disable this
- feature for lynx, because it is implemented in linux-low.c instead
- of in generic code. */
- NULL, /* supports_conditional_breakpoints */
+ target_can_do_hardware_single_step,
NULL, /* stopped_by_watchpoint */
NULL, /* stopped_data_address */
NULL, /* read_offsets */
NULL, /* get_tls_address */
- NULL, /* qxfer_spu */
NULL, /* hostio_last_error */
NULL, /* qxfer_osdata */
NULL, /* qxfer_siginfo */
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 */
};