btrace: check perf_event_paranoid
authorMarkus Metzger <markus.t.metzger@intel.com>
Fri, 19 Jan 2018 14:17:43 +0000 (15:17 +0100)
committerMarkus Metzger <markus.t.metzger@intel.com>
Fri, 9 Feb 2018 13:03:21 +0000 (14:03 +0100)
One recurring error on Debian systems is that the default perf_event_paranoid
setting disables the perf_event interface for user-space.

Check the current level and point the user to the file.

gdb/
* nat/linux-btrace.c (diagnose_perf_event_open_fail): New.
(linux_enable_pt, linux_enable_bts): Call
diagnose_perf_event_open_fail.

gdb/ChangeLog
gdb/nat/linux-btrace.c

index 769858b764840840c750dd72929d187efd81c4e6..fd8a6249f82294f96cdaba059debed604f0c2c37 100644 (file)
@@ -1,3 +1,9 @@
+2018-02-09  Markus Metzger  <markus.t.metzger@intel.com>
+
+       * nat/linux-btrace.c (diagnose_perf_event_open_fail): New.
+       (linux_enable_pt, linux_enable_bts): Call
+       diagnose_perf_event_open_fail.
+
 2018-02-09  Markus Metzger  <markus.t.metzger@intel.com>
 
        * nat/linux-btrace.c (perf_event_pt_event_type): Improve error message.
index 301649b4983f1982a435aaad6a46b6eb28f1c2d9..8eadf7a5063b1887f0126cae91a238f7047ee341 100644 (file)
@@ -409,6 +409,34 @@ cpu_supports_bts (void)
     }
 }
 
+/* The perf_event_open syscall failed.  Try to print a helpful error
+   message.  */
+
+static void
+diagnose_perf_event_open_fail ()
+{
+  switch (errno)
+    {
+    case EPERM:
+    case EACCES:
+      {
+       static const char filename[] = "/proc/sys/kernel/perf_event_paranoid";
+       gdb_file_up file = gdb_fopen_cloexec (filename, "r");
+       if (file.get () == nullptr)
+         break;
+
+       int level, found = fscanf (file.get (), "%d", &level);
+       if (found == 1 && level > 2)
+         error (_("You do not have permission to record the process.  "
+                  "Try setting %s to 2 or less."), filename);
+      }
+
+      break;
+    }
+
+  error (_("Failed to start recording: %s"), safe_strerror (errno));
+}
+
 /* Enable branch tracing in BTS format.  */
 
 static struct btrace_target_info *
@@ -448,7 +476,7 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
   errno = 0;
   scoped_fd fd (syscall (SYS_perf_event_open, &bts->attr, pid, -1, -1, 0));
   if (fd.get () < 0)
-    error (_("Failed to start recording: %s"), safe_strerror (errno));
+    diagnose_perf_event_open_fail ();
 
   /* Convert the requested size in bytes to pages (rounding up).  */
   pages = ((size_t) conf->size / PAGE_SIZE
@@ -578,7 +606,7 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
   errno = 0;
   scoped_fd fd (syscall (SYS_perf_event_open, &pt->attr, pid, -1, -1, 0));
   if (fd.get () < 0)
-    error (_("Failed to start recording: %s"), safe_strerror (errno));
+    diagnose_perf_event_open_fail ();
 
   /* Allocate the configuration page. */
   scoped_mmap data (nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,