/* Low level interface to ptrace, for the remote server for GDB.
- Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ Copyright (C) 1995-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "server.h"
#include "linux-low.h"
#include "nat/linux-osdata.h"
-#include "agent.h"
+#include "common/agent.h"
#include "tdesc.h"
-#include "rsp-low.h"
-#include "signals-state-save-restore.h"
+#include "common/rsp-low.h"
+#include "common/signals-state-save-restore.h"
#include "nat/linux-nat.h"
#include "nat/linux-waitpid.h"
-#include "gdb_wait.h"
+#include "common/gdb_wait.h"
#include "nat/gdb_ptrace.h"
#include "nat/linux-ptrace.h"
#include "nat/linux-procfs.h"
#include <sys/stat.h>
#include <sys/vfs.h>
#include <sys/uio.h>
-#include "filestuff.h"
+#include "common/filestuff.h"
#include "tracepoint.h"
#include "hostio.h"
#include <inttypes.h>
-#include "common-inferior.h"
+#include "common/common-inferior.h"
#include "nat/fork-inferior.h"
-#include "environ.h"
+#include "common/environ.h"
#include "common/scoped_restore.h"
#ifndef ELFMAG0
/* Don't include <linux/elf.h> here. If it got included by gdb_proc_service.h
#ifdef HAVE_LINUX_BTRACE
# include "nat/linux-btrace.h"
-# include "btrace-common.h"
+# include "common/btrace-common.h"
#endif
#ifndef HAVE_ELF32_AUXV_T
struct thread_info *child_thr;
struct target_desc *tdesc;
- ptid = ptid_build (new_pid, new_pid, 0);
+ ptid = ptid_t (new_pid, new_pid, 0);
if (debug_threads)
{
debug_printf ("HEW: Got fork event from LWP %ld, "
"new child is %d\n",
- ptid_get_lwp (ptid_of (event_thr)),
- ptid_get_pid (ptid));
+ ptid_of (event_thr).lwp (),
+ ptid.pid ());
}
/* Add the new process to the tables and clone the breakpoint
"from LWP %ld, new child is LWP %ld\n",
lwpid_of (event_thr), new_pid);
- ptid = ptid_build (pid_of (event_thr), new_pid, 0);
+ ptid = ptid_t (pid_of (event_thr), new_pid, 0);
new_lwp = add_lwp (ptid);
/* Either we're going to immediately resume the new thread
/* Get the event ptid. */
event_ptid = ptid_of (event_thr);
- event_pid = ptid_get_pid (event_ptid);
+ event_pid = event_ptid.pid ();
/* Save the syscall list from the execing process. */
proc = get_thread_process (event_thr);
lwp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
+ lwp->thread = add_thread (ptid, lwp);
+
if (the_low_target.new_thread != NULL)
the_low_target.new_thread (lwp);
- lwp->thread = add_thread (ptid, lwp);
-
return lwp;
}
linux_add_process (pid, 0);
- ptid = ptid_build (pid, pid, 0);
+ ptid = ptid_t (pid, pid, 0);
new_lwp = add_lwp (ptid);
new_lwp->must_set_ptrace_flags = 1;
linux_attach_lwp (ptid_t ptid)
{
struct lwp_info *new_lwp;
- int lwpid = ptid_get_lwp (ptid);
+ int lwpid = ptid.lwp ();
if (ptrace (PTRACE_ATTACH, lwpid, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0)
!= 0)
/* Is this a new thread? */
if (find_thread_ptid (ptid) == NULL)
{
- int lwpid = ptid_get_lwp (ptid);
+ int lwpid = ptid.lwp ();
int err;
if (debug_threads)
{
struct process_info *proc;
struct thread_info *initial_thread;
- ptid_t ptid = ptid_build (pid, pid, 0);
+ ptid_t ptid = ptid_t (pid, pid, 0);
int err;
+ proc = linux_add_process (pid, 1);
+
/* Attach to PID. We will check for other threads
soon. */
err = linux_attach_lwp (ptid);
if (err != 0)
{
- std::string reason = linux_ptrace_attach_fail_reason_string (ptid, err);
+ remove_process (proc);
+ std::string reason = linux_ptrace_attach_fail_reason_string (ptid, err);
error ("Cannot attach to process %ld: %s", pid, reason.c_str ());
}
- proc = linux_add_process (pid, 1);
-
/* Don't ignore the initial SIGSTOP if we just attached to this
process. It will be collected by wait shortly. */
- initial_thread = find_thread_ptid (ptid_build (pid, pid, 0));
+ initial_thread = find_thread_ptid (ptid_t (pid, pid, 0));
initial_thread->last_resume_kind = resume_stop;
/* We must attach to every LWP. If /proc is mounted, use that to
{
struct lwp_info *lwp;
int wstat, lwpid;
- ptid_t pid_ptid = pid_to_ptid (pid);
+ ptid_t pid_ptid = ptid_t (pid);
lwpid = linux_wait_for_event_filtered (pid_ptid, pid_ptid,
&wstat, __WALL);
gdb_assert (lwpid > 0);
- lwp = find_lwp_pid (pid_to_ptid (lwpid));
+ lwp = find_lwp_pid (ptid_t (lwpid));
if (!WIFSTOPPED (wstat) || WSTOPSIG (wstat) != SIGSTOP)
{
{
bool seen_one = false;
- thread_info *thread = find_thread (pid, [&] (thread_info *thread)
+ thread_info *thread = find_thread (pid, [&] (thread_info *thr_arg)
{
if (!seen_one)
{
kill_wait_lwp (struct lwp_info *lwp)
{
struct thread_info *thr = get_lwp_thread (lwp);
- int pid = ptid_get_pid (ptid_of (thr));
- int lwpid = ptid_get_lwp (ptid_of (thr));
+ int pid = ptid_of (thr).pid ();
+ int lwpid = ptid_of (thr).lwp ();
int wstat;
int res;
}
static int
-linux_kill (int pid)
+linux_kill (process_info *process)
{
- struct process_info *process;
- struct lwp_info *lwp;
-
- process = find_process_pid (pid);
- if (process == NULL)
- return -1;
+ int pid = process->pid;
/* If we're killing a running inferior, make sure it is stopped
first, as PTRACE_KILL will not work otherwise. */
/* See the comment in linux_kill_one_lwp. We did not kill the first
thread in the list, so do so now. */
- lwp = find_lwp_pid (pid_to_ptid (pid));
+ lwp_info *lwp = find_lwp_pid (ptid_t (pid));
if (lwp == NULL)
{
}
static int
-linux_detach (int pid)
+linux_detach (process_info *process)
{
- struct process_info *process;
struct lwp_info *main_lwp;
- process = find_process_pid (pid);
- if (process == NULL)
- return -1;
-
/* As there's a step over already in progress, let it finish first,
otherwise nesting a stabilize_threads operation on top gets real
messy. */
/* Detach from the clone lwps first. If the thread group exits just
while we're detaching, we must reap the clone lwps before we're
able to reap the leader. */
- for_each_thread (pid, linux_detach_lwp_callback);
+ for_each_thread (process->pid, linux_detach_lwp_callback);
- main_lwp = find_lwp_pid (pid_to_ptid (pid));
+ main_lwp = find_lwp_pid (ptid_t (process->pid));
linux_detach_one_lwp (main_lwp);
the_target->mourn (process);
struct lwp_info *
find_lwp_pid (ptid_t ptid)
{
- thread_info *thread = find_thread ([&] (thread_info *thread)
+ thread_info *thread = find_thread ([&] (thread_info *thr_arg)
{
int lwp = ptid.lwp () != 0 ? ptid.lwp () : ptid.pid ();
- return thread->id.lwp () == lwp;
+ return thr_arg->id.lwp () == lwp;
});
if (thread == NULL)
struct lwp_info *
iterate_over_lwps (ptid_t filter,
- iterate_over_lwps_ftype callback,
- void *data)
+ gdb::function_view<iterate_over_lwps_ftype> callback)
{
- thread_info *thread = find_thread (filter, [&] (thread_info *thread)
+ thread_info *thread = find_thread (filter, [&] (thread_info *thr_arg)
{
- lwp_info *lwp = get_thread_lwp (thread);
+ lwp_info *lwp = get_thread_lwp (thr_arg);
- return callback (lwp, data);
+ return callback (lwp);
});
if (thread == NULL)
pid_t leader_pid = pid_of (proc);
struct lwp_info *leader_lp;
- leader_lp = find_lwp_pid (pid_to_ptid (leader_pid));
+ leader_lp = find_lwp_pid (ptid_t (leader_pid));
if (debug_threads)
debug_printf ("leader_pid=%d, leader_lp!=NULL=%d, "
struct thread_info *thread;
int have_stop_pc = 0;
- child = find_lwp_pid (pid_to_ptid (lwpid));
+ child = find_lwp_pid (ptid_t (lwpid));
/* Check for stop events reported by a process we didn't already
know about - anything not already in our LWP list.
"after exec.\n", lwpid);
}
- child_ptid = ptid_build (lwpid, lwpid, 0);
+ child_ptid = ptid_t (lwpid, lwpid, 0);
child = add_lwp (child_ptid);
child->stopped = 1;
current_thread = child->thread;
/* Check for a lwp with a pending status. */
- if (ptid_equal (filter_ptid, minus_one_ptid) || ptid_is_pid (filter_ptid))
+ if (filter_ptid == minus_one_ptid || filter_ptid.is_pid ())
{
event_thread = find_thread_in_random ([&] (thread_info *thread)
{
if (debug_threads && event_thread)
debug_printf ("Got a pending child %ld\n", lwpid_of (event_thread));
}
- else if (!ptid_equal (filter_ptid, null_ptid))
+ else if (filter_ptid != null_ptid)
{
requested_child = find_lwp_pid (filter_ptid);
else
any_resumed = 0;
- if (ptid_equal (step_over_bkpt, null_ptid))
+ if (step_over_bkpt == null_ptid)
pid = linux_wait_for_event (ptid, &w, options);
else
{
if it's not the single_step_breakpoint we are hitting.
This avoids that a program would keep trapping a permanent breakpoint
forever. */
- if (!ptid_equal (step_over_bkpt, null_ptid)
+ if (step_over_bkpt != null_ptid
&& event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
&& (event_child->stepping
|| !single_step_breakpoint_inserted_here (event_child->stop_pc)))
from among those that have had events. Giving equal priority
to all LWPs that have had events helps prevent
starvation. */
- if (ptid_equal (ptid, minus_one_ptid))
+ if (ptid == minus_one_ptid)
{
event_child->status_pending_p = 1;
event_child->status_pending = w;
ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (w));
}
- gdb_assert (ptid_equal (step_over_bkpt, null_ptid));
+ gdb_assert (step_over_bkpt == null_ptid);
if (debug_threads)
{
event_ptid = linux_wait_1 (ptid, ourstatus, target_options);
}
while ((target_options & TARGET_WNOHANG) == 0
- && ptid_equal (event_ptid, null_ptid)
+ && event_ptid == null_ptid
&& ourstatus->kind == TARGET_WAITKIND_IGNORE);
/* If at least one stop was reported, there may be more. A single
SIGCHLD can signal more than one child stop. */
if (target_is_async_p ()
&& (target_options & TARGET_WNOHANG) != 0
- && !ptid_equal (event_ptid, null_ptid))
+ && event_ptid != null_ptid)
async_file_mark ();
return event_ptid;
for (int ndx = 0; ndx < n; ndx++)
{
ptid_t ptid = resume[ndx].thread;
- if (ptid_equal (ptid, minus_one_ptid)
+ if (ptid == minus_one_ptid
|| ptid == thread->id
/* Handle both 'pPID' and 'pPID.-1' as meaning 'all threads
of PID'. */
- || (ptid_get_pid (ptid) == pid_of (thread)
- && (ptid_is_pid (ptid)
- || ptid_get_lwp (ptid) == -1)))
+ || (ptid.pid () == pid_of (thread)
+ && (ptid.is_pid ()
+ || ptid.lwp () == -1)))
{
if (resume[ndx].kind == resume_stop
&& thread->last_resume_kind == resume_stop)
static void
complete_ongoing_step_over (void)
{
- if (!ptid_equal (step_over_bkpt, null_ptid))
+ if (step_over_bkpt != null_ptid)
{
struct lwp_info *lwp;
int wstat;
#endif
if (res < 0)
{
- if (errno == EIO)
+ if (errno == EIO
+ || (errno == EINVAL && regset->type == OPTIONAL_REGS))
{
- /* If we get EIO on a regset, do not try it again for
- this process mode. */
+ /* If we get EIO on a regset, or an EINVAL and the regset is
+ optional, do not try it again for this process mode. */
disable_regset (regsets_info, regset);
}
else if (errno == ENODATA)
if (res < 0)
{
- if (errno == EIO)
+ if (errno == EIO
+ || (errno == EINVAL && regset->type == OPTIONAL_REGS))
{
- /* If we get EIO on a regset, do not try it again for
- this process mode. */
+ /* If we get EIO on a regset, or an EINVAL and the regset is
+ optional, do not try it again for this process mode. */
disable_regset (regsets_info, regset);
}
else if (errno == ESRCH)
{
const char *sep;
CORE_ADDR *addrp;
- int len;
+ int name_len;
sep = strchr (annex, '=');
if (sep == NULL)
break;
- len = sep - annex;
- if (len == 5 && startswith (annex, "start"))
+ name_len = sep - annex;
+ if (name_len == 5 && startswith (annex, "start"))
addrp = &lm_addr;
- else if (len == 4 && startswith (annex, "prev"))
+ else if (name_len == 4 && startswith (annex, "prev"))
addrp = &lm_prev;
else
{
enum btrace_error err;
int i;
- btrace_data_init (&btrace);
-
err = linux_read_btrace (&btrace, tinfo, type);
if (err != BTRACE_ERR_NONE)
{
else
buffer_grow_str0 (buffer, "E.Generic Error.");
- goto err;
+ return -1;
}
switch (btrace.format)
{
case BTRACE_FORMAT_NONE:
buffer_grow_str0 (buffer, "E.No Trace.");
- goto err;
+ return -1;
case BTRACE_FORMAT_BTS:
buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
default:
buffer_grow_str0 (buffer, "E.Unsupported Trace Format.");
- goto err;
+ return -1;
}
- btrace_data_fini (&btrace);
return 0;
-
-err:
- btrace_data_fini (&btrace);
- return -1;
}
/* See to_btrace_conf target method. */
return pc;
}
+/* Fetch the entry MATCH from the auxv vector, where entries are length
+ WORDSIZE. If no entry was found, return zero. */
+
+static CORE_ADDR
+linux_get_auxv (int wordsize, CORE_ADDR match)
+{
+ gdb_byte *data = (gdb_byte *) alloca (2 * wordsize);
+ int offset = 0;
+
+ gdb_assert (wordsize == 4 || wordsize == 8);
+
+ while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
+ {
+ if (wordsize == 4)
+ {
+ uint32_t *data_p = (uint32_t *)data;
+ if (data_p[0] == match)
+ return data_p[1];
+ }
+ else
+ {
+ uint64_t *data_p = (uint64_t *)data;
+ if (data_p[0] == match)
+ return data_p[1];
+ }
+
+ offset += 2 * wordsize;
+ }
+
+ return 0;
+}
+
+/* See linux-low.h. */
+
+CORE_ADDR
+linux_get_hwcap (int wordsize)
+{
+ return linux_get_auxv (wordsize, AT_HWCAP);
+}
+
+/* See linux-low.h. */
+
+CORE_ADDR
+linux_get_hwcap2 (int wordsize)
+{
+ return linux_get_auxv (wordsize, AT_HWCAP2);
+}
static struct target_ops linux_target_ops = {
linux_create_inferior,
set_target_ops (&linux_target_ops);
linux_ptrace_init_warnings ();
+ linux_proc_init_warnings ();
sigchld_action.sa_handler = sigchld_handler;
sigemptyset (&sigchld_action.sa_mask);