]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[Morello] Add capability fault codes and report fault information
authorLuis Machado <luis.machado@arm.com>
Thu, 3 Sep 2020 17:20:46 +0000 (14:20 -0300)
committerJohn Baldwin <jhb@FreeBSD.org>
Thu, 1 Sep 2022 22:53:22 +0000 (15:53 -0700)
Report capability faults with additional information, like tag, bounds,
sealed permissions and access faults.

gdb/ChangeLog

2020-10-20  Luis Machado  <luis.machado@arm.com>

* aarch64-linux-tdep.c: Include value.h.
(aarch64_linux_report_signal_info): New function.
(aarch64_linux_init_abi): Register hook for reporting signal
information.
* arch/aarch64-cap-linux.h (SEGV_CAPTAGERR, SEGV_CAPSEALEDERR)
(SEGV_CAPBOUNDSERR, SEGV_CAPPERMERR, SEGV_CAPSTORETAGERR): New
constants.

gdb/aarch64-linux-tdep.c
gdb/arch/aarch64-cap-linux.h

index 10f0bf7291631d3030175a604a89a3a6ff8d1ce8..29e5051dd6378fa6ecfde8aa8c8c3a3c4c36165f 100644 (file)
@@ -1741,7 +1741,8 @@ aarch64_linux_memtag_to_string (struct gdbarch *gdbarch, struct value *tag_value
 }
 
 /* AArch64 Linux implementation of the report_signal_info gdbarch
-   hook.  Displays information about possible memory tag violations.  */
+   hook.  Displays information about possible memory tag violations or
+   capability violations.  */
 
 static void
 aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
@@ -1750,7 +1751,8 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
 {
   aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
-  if (!tdep->has_mte () || siggnal != GDB_SIGNAL_SEGV)
+  if ((!tdep->has_mte () && !!tdep->has_capability ())
+      || siggnal != GDB_SIGNAL_SEGV)
     return;
 
   CORE_ADDR fault_addr = 0;
@@ -1758,8 +1760,8 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
 
   try
     {
-      /* Sigcode tells us if the segfault is actually a memory tag
-        violation.  */
+      /* Sigcode tells us if the segfault is actually a memory tag or
+        capability violation.  */
       si_code = parse_and_eval_long ("$_siginfo.si_code");
 
       fault_addr
@@ -1771,40 +1773,83 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
       return;
     }
 
-  /* If this is not a memory tag violation, just return.  */
-  if (si_code != SEGV_MTEAERR && si_code != SEGV_MTESERR)
+  /* If this is not a memory tag or capability violation, just return.  */
+  if (si_code != SEGV_MTEAERR && si_code != SEGV_MTESERR
+      && si_code != SEGV_CAPTAGERR && si_code != SEGV_CAPSEALEDERR
+      && si_code != SEGV_CAPBOUNDSERR && si_code != SEGV_CAPPERMERR
+      && si_code != SEGV_CAPSTORETAGERR)
     return;
 
   uiout->text ("\n");
 
-  uiout->field_string ("sigcode-meaning", _("Memory tag violation"));
-
-  /* For synchronous faults, show additional information.  */
-  if (si_code == SEGV_MTESERR)
+  switch (si_code)
     {
-      uiout->text (_(" while accessing address "));
-      uiout->field_core_addr ("fault-addr", gdbarch, fault_addr);
-      uiout->text ("\n");
+      case SEGV_MTEAERR:
+      case SEGV_MTESERR:
+       uiout->field_string ("sigcode-meaning", _("Memory tag violation"));
 
-      gdb::optional<CORE_ADDR> atag
-       = aarch64_mte_get_atag (address_significant (gdbarch, fault_addr));
-      gdb_byte ltag = aarch64_mte_get_ltag (fault_addr);
+       /* For synchronous faults, show additional information.  */
+       if (si_code == SEGV_MTESERR)
+         {
+           uiout->text (_(" while accessing address "));
+           uiout->field_core_addr ("fault-addr", gdbarch, fault_addr);
+           uiout->text ("\n");
 
-      if (!atag.has_value ())
-       uiout->text (_("Allocation tag unavailable"));
-      else
-       {
-         uiout->text (_("Allocation tag "));
-         uiout->field_string ("allocation-tag", hex_string (*atag));
-         uiout->text ("\n");
-         uiout->text (_("Logical tag "));
-         uiout->field_string ("logical-tag", hex_string (ltag));
-       }
-    }
-  else
-    {
-      uiout->text ("\n");
-      uiout->text (_("Fault address unavailable"));
+           gdb::optional<CORE_ADDR> atag
+             = aarch64_mte_get_atag (address_significant (gdbarch, fault_addr));
+           gdb_byte ltag = aarch64_mte_get_ltag (fault_addr);
+
+           if (!atag.has_value ())
+             uiout->text (_("Allocation tag unavailable"));
+           else
+             {
+               uiout->text (_("Allocation tag "));
+               uiout->field_string ("allocation-tag", hex_string (*atag));
+               uiout->text ("\n");
+               uiout->text (_("Logical tag "));
+               uiout->field_string ("logical-tag", hex_string (ltag));
+             }
+         }
+       else
+         {
+           uiout->text ("\n");
+           uiout->text (_("Fault address unavailable"));
+         }
+       break;
+      case SEGV_CAPTAGERR:
+      case SEGV_CAPSEALEDERR:
+      case SEGV_CAPBOUNDSERR:
+      case SEGV_CAPPERMERR:
+      case SEGV_CAPSTORETAGERR:
+       std::string str_si_code;
+
+       switch (si_code)
+         {
+           case SEGV_CAPTAGERR:
+             str_si_code = "tag";
+             break;
+           case SEGV_CAPSEALEDERR:
+             str_si_code = "sealed";
+             break;
+           case SEGV_CAPBOUNDSERR:
+             str_si_code = "bounds";
+             break;
+           case SEGV_CAPPERMERR:
+             str_si_code = "permission";
+             break;
+           case SEGV_CAPSTORETAGERR:
+             str_si_code = "access";
+             break;
+         }
+
+       std::string str_meaning = "Capability " + str_si_code + " fault";
+       uiout->field_string ("sigcode-meaning", str_meaning);
+
+       /* FIXME-Morello: Show more information about the faults.  */
+       uiout->text (_(" while accessing address "));
+       uiout->field_core_addr ("fault-addr", gdbarch, fault_addr);
+       uiout->text ("\n");
+       break;
     }
 }
 
@@ -2234,6 +2279,12 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
                                            aarch64_displaced_step_hw_singlestep);
 
   set_gdbarch_gcc_target_options (gdbarch, aarch64_linux_gcc_target_options);
+
+  if (tdep->has_capability ())
+    {
+      set_gdbarch_report_signal_info (gdbarch,
+                                     aarch64_linux_report_signal_info);
+    }
 }
 
 #if GDB_SELF_TEST
index f62bc7f2f8dc6c855a78b5f0ceb58149192d1d54..519c9b25cd6ecc56c4367a548879e9b5a81b433c 100644 (file)
 #define AARCH64_MORELLO_REGS_NUM 41
 #define AARCH64_C_REGS_NUM 31
 
+/* Capability fault si_code numbers.  */
+#define SEGV_CAPTAGERR       10  /* Capability tag fault */
+#define SEGV_CAPSEALEDERR     11  /* Capability sealed fault */
+#define SEGV_CAPBOUNDSERR     12  /* Capability bounds fault */
+#define SEGV_CAPPERMERR              13  /* Capability permission fault */
+#define SEGV_CAPSTORETAGERR   14  /* Capability tag store fault */
+
 #endif /*ARCH_AARCH64_CAP_LINUX_H */