AArch64: Report tag violation error information
authorLuis Machado <luis.machado@linaro.org>
Mon, 15 Jun 2020 18:44:20 +0000 (15:44 -0300)
committerLuis Machado <luis.machado@linaro.org>
Wed, 24 Mar 2021 17:56:07 +0000 (14:56 -0300)
Whenever a memory tag violation occurs, we get a SIGSEGV. Additional
information can be obtained through the siginfo data structure.

For AArch64 the Linux kernel may expose the fault address and tag
information, if we have a synchronous event. Otherwise there is
no fault address available.

The synchronous event looks like this:

--
(gdb) continue
Continuing.

Program received signal SIGSEGV, Segmentation fault
Memory tag violation while accessing address 0x0500fffff7ff8000
Allocation tag 0x1.
Logical tag 0x5
--

The asynchronous event looks like this:

--
(gdb) continue
Continuing.

Program received signal SIGSEGV, Segmentation fault
Memory tag violation
Fault address unavailable.
--

gdb/ChangeLog:

2021-03-24  Luis Machado  <luis.machado@linaro.org>

* aarch64-linux-tdep.c
(aarch64_linux_report_signal_info): New function.
(aarch64_linux_init_abi): Register
aarch64_linux_report_signal_info as the report_signal_info hook.
* arch/aarch64-linux.h (SEGV_MTEAERR): Define.
(SEGV_MTESERR): Define.

gdb/ChangeLog
gdb/aarch64-linux-tdep.c
gdb/arch/aarch64-mte-linux.h

index ce3373ba9d0d5476a34d97e9c596d8733f8a8112..52e0ddeb2b4d1846361f62d85c3956642ee62208 100644 (file)
@@ -1,3 +1,12 @@
+2021-03-24  Luis Machado  <luis.machado@linaro.org>
+
+       * aarch64-linux-tdep.c
+       (aarch64_linux_report_signal_info): New function.
+       (aarch64_linux_init_abi): Register
+       aarch64_linux_report_signal_info as the report_signal_info hook.
+       * arch/aarch64-linux.h (SEGV_MTEAERR): Define.
+       (SEGV_MTESERR): Define.
+
 2021-03-24  Luis Machado  <luis.machado@linaro.org>
 
        * aarch64-linux-tdep.c: Include gdbsupport/selftest.h.
index e71f062e25d58ee810945c46448e0619d75f91e9..15bbdb253f956a2941a782eda74a6b35b64614e4 100644 (file)
@@ -1685,6 +1685,73 @@ aarch64_linux_memtag_to_string (struct gdbarch *gdbarch, struct value *tag_value
   return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
 }
 
+/* AArch64 Linux implementation of the report_signal_info gdbarch
+   hook.  Displays information about possible memory tag violations.  */
+
+static void
+aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
+                                 struct ui_out *uiout,
+                                 enum gdb_signal siggnal)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->has_mte () || siggnal != GDB_SIGNAL_SEGV)
+    return;
+
+  CORE_ADDR fault_addr = 0;
+  long si_code = 0;
+
+  try
+    {
+      /* Sigcode tells us if the segfault is actually a memory tag
+        violation.  */
+      si_code = parse_and_eval_long ("$_siginfo.si_code");
+
+      fault_addr
+       = parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr");
+    }
+  catch (const gdb_exception_error &exception)
+    {
+      exception_print (gdb_stderr, exception);
+      return;
+    }
+
+  /* If this is not a memory tag violation, just return.  */
+  if (si_code != SEGV_MTEAERR && si_code != SEGV_MTESERR)
+    return;
+
+  uiout->text ("\n");
+
+  uiout->field_string ("sigcode-meaning", _("Memory tag violation"));
+
+  /* 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");
+
+      gdb::optional<CORE_ADDR> atag = aarch64_mte_get_atag (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"));
+    }
+}
+
 static void
 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -1765,6 +1832,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
       /* Register a hook for converting a memory tag to a string.  */
       set_gdbarch_memtag_to_string (gdbarch, aarch64_linux_memtag_to_string);
+
+      set_gdbarch_report_signal_info (gdbarch,
+                                     aarch64_linux_report_signal_info);
     }
 
   /* Initialize the aarch64_linux_record_tdep.  */
index f517638831cabedd454d9a62fb4981f621f3842b..2aa97eb861a16a7b7d5b842ab64bcd5ccf118469 100644 (file)
 #define AARCH64_MTE_LOGICAL_TAG_START_BIT 56
 #define AARCH64_MTE_LOGICAL_MAX_VALUE 0xf
 
+/* Memory tagging definitions.  */
+#ifndef SEGV_MTEAERR
+# define SEGV_MTEAERR 8
+# define SEGV_MTESERR 9
+#endif
+
 /* Memory tag types for AArch64.  */
 enum class aarch64_memtag_type
 {