]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/gdbserver/linux-low.c
gdbserver: Add linux_get_hwcap
[thirdparty/binutils-gdb.git] / gdb / gdbserver / linux-low.c
index f8507b79684fa34f1931eee8aa71a468f9d217b3..7158a6798c91f42670a232343b252d5f835da999 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -523,14 +523,14 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
          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
@@ -630,7 +630,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
                      "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
@@ -699,7 +699,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
 
       /* 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);
@@ -951,11 +951,11 @@ add_lwp (ptid_t ptid)
 
   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;
 }
 
@@ -1017,7 +1017,7 @@ linux_create_inferior (const char *program,
 
   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;
 
@@ -1052,7 +1052,7 @@ int
 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)
@@ -1140,7 +1140,7 @@ attach_proc_task_lwp_callback (ptid_t ptid)
   /* 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)
@@ -1185,24 +1185,25 @@ linux_attach (unsigned long pid)
 {
   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
@@ -1226,13 +1227,13 @@ linux_attach (unsigned long pid)
     {
       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)
        {
@@ -1255,7 +1256,7 @@ last_thread_of_process_p (int pid)
 {
   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)
        {
@@ -1323,8 +1324,8 @@ static void
 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;
 
@@ -1385,14 +1386,9 @@ kill_one_lwp_callback (thread_info *thread, int pid)
 }
 
 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.  */
@@ -1405,7 +1401,7 @@ linux_kill (int pid)
 
   /* 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)
     {
@@ -1608,15 +1604,10 @@ linux_detach_lwp_callback (thread_info *thread)
 }
 
 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.  */
@@ -1638,9 +1629,9 @@ linux_detach (int pid)
   /* 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);
@@ -1821,10 +1812,10 @@ status_pending_p_callback (thread_info *thread, ptid_t ptid)
 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)
@@ -1852,14 +1843,13 @@ num_lwps (int pid)
 
 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)
@@ -1878,7 +1868,7 @@ check_zombie_leaders (void)
     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, "
@@ -2363,7 +2353,7 @@ linux_low_filter_event (int lwpid, int wstat)
   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.
@@ -2391,7 +2381,7 @@ linux_low_filter_event (int lwpid, int wstat)
                        "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;
@@ -2635,7 +2625,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
 
   /* 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)
        {
@@ -2647,7 +2637,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
       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);
 
@@ -3159,7 +3149,7 @@ linux_wait_1 (ptid_t 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
     {
@@ -3248,7 +3238,7 @@ linux_wait_1 (ptid_t ptid,
      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)))
@@ -3736,7 +3726,7 @@ linux_wait_1 (ptid_t ptid,
         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;
@@ -3827,7 +3817,7 @@ linux_wait_1 (ptid_t ptid,
       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)
     {
@@ -3886,14 +3876,14 @@ linux_wait (ptid_t ptid,
       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;
@@ -4542,13 +4532,13 @@ linux_set_resume_request (thread_info *thread, thread_resume *resume, size_t n)
   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)
@@ -4899,7 +4889,7 @@ finish_step_over (struct lwp_info *lwp)
 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;
@@ -5368,10 +5358,11 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
 #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)
@@ -5466,10 +5457,11 @@ regsets_store_inferior_registers (struct regsets_info *regsets_info,
 
       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)
@@ -7042,16 +7034,16 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
     {
       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
        {
@@ -7250,8 +7242,6 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
   enum btrace_error err;
   int i;
 
-  btrace_data_init (&btrace);
-
   err = linux_read_btrace (&btrace, tinfo, type);
   if (err != BTRACE_ERR_NONE)
     {
@@ -7260,14 +7250,14 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
       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");
@@ -7298,15 +7288,10 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
 
     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.  */
@@ -7438,6 +7423,53 @@ linux_get_pc_64bit (struct regcache *regcache)
   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,
@@ -7565,6 +7597,7 @@ initialize_low (void)
   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);