]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Handle C regset write warnings better in GDBServer
authorLuis Machado <luis.machado@linaro.org>
Mon, 29 Nov 2021 12:19:39 +0000 (09:19 -0300)
committerJohn Baldwin <jhb@FreeBSD.org>
Thu, 1 Sep 2022 22:59:24 +0000 (15:59 -0700)
GDBServer handles register reads/writes a bit differently compared to GDB.

Since C register writes are only allowed with cheri.ptrace_forge_cap=1,
GDBServer will keep issuing warnings if such setting is 0.

This patch improves it by issuing a single more helpful warning to the
user. If cheri.ptrace_forge_cap is flipped, the warning will be issued
again appropriately to remind the user about it.

Bug-ID: https://git.morello-project.org/morello/binutils-gdb/-/issues/5

gdbserver/linux-aarch64-low.cc
gdbserver/linux-low.cc
gdbserver/linux-low.h

index b8929ef4bab1a5bac53aec5b510e3562e656ac4d..131c48ecdd3e4405d8ea4d4111673b6e42018ab0 100644 (file)
@@ -816,7 +816,9 @@ static struct regset_info aarch64_regsets[] =
   /* FIXME-Morello: Fixup the register set size.  */
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_MORELLO,
     0, OPTIONAL_REGS,
-    aarch64_fill_cregset, aarch64_store_cregset },
+    aarch64_fill_cregset, aarch64_store_cregset, nullptr,
+    "cheri.ptrace_forge_cap"
+  },
   NULL_REGSET
 };
 
@@ -874,7 +876,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
          break;
        case NT_ARM_MORELLO:
          if (features.capability)
-           regset->size = AARCH64_LINUX_CREGS_SIZE;
+           {
+             regset->size = AARCH64_LINUX_CREGS_SIZE;
+             regset->sysctl_write_should_warn = true;
+           }
          break;
        default:
          gdb_assert_not_reached ("Unknown register set found.");
index 2ab3a8794c12259ed41924e68c8254b91e63fcb6..56be6e8edc6ffac036fdc245f500489fd9b5c1fe 100644 (file)
@@ -5025,6 +5025,16 @@ regsets_store_inferior_registers (struct regsets_info *regsets_info,
              free (buf);
              return 0;
            }
+         else if (errno == EPERM && regset->sysctl_write_permission != nullptr)
+           {
+             if (regset->sysctl_write_should_warn)
+               {
+                 warning ("Unable to store registers.\n"
+                          "Please run \"sysctl %s=1\".",
+                          regset->sysctl_write_permission);
+                 regset->sysctl_write_should_warn = false;
+               }
+           }
          else
            {
              perror ("Warning: ptrace(regsets_store_inferior_registers)");
@@ -5032,6 +5042,17 @@ regsets_store_inferior_registers (struct regsets_info *regsets_info,
        }
       else if (regset->type == GENERAL_REGS)
        saw_general_regs = 1;
+      else
+       {
+         /* We've succeeded in writing the registers. If this register set
+            has a sysctl permission flag and the warnings are disabled,
+            re-enable it so we can issue a warning next time the write
+            attempt fails.  */
+         if (regset->sysctl_write_permission != nullptr
+             && !regset->sysctl_write_should_warn)
+           regset->sysctl_write_should_warn = true;
+       }
+
       free (buf);
     }
   if (saw_general_regs)
index 9edf446865039c87f7eee50813e27093fdb28174..1f98039e485d20258159211e28804c78fc47a776 100644 (file)
@@ -48,7 +48,7 @@ enum regset_type {
 /* The arch's regsets array initializer must be terminated with a NULL
    regset.  */
 #define NULL_REGSET \
-  { 0, 0, 0, -1, (enum regset_type) -1, NULL, NULL }
+  { 0, 0, 0, -1, (enum regset_type) -1, nullptr, nullptr, nullptr, nullptr }
 
 struct regset_info
 {
@@ -60,6 +60,13 @@ struct regset_info
   enum regset_type type;
   regset_fill_func fill_function;
   regset_store_func store_function;
+  /* The name of the sysctl flag that controls read/write permission for this
+     particular register set.  If it is nullptr, it means there is no such
+     switch.  */
+  const char *sysctl_read_permission = nullptr;
+  const char *sysctl_write_permission = nullptr;
+  bool sysctl_read_should_warn = true;
+  bool sysctl_write_should_warn = true;
 };
 
 /* Aggregation of all the supported regsets of a given