From cf44c9fa1b94837b093752854370b9c2db531264 Mon Sep 17 00:00:00 2001 From: Luis Machado Date: Mon, 15 Jun 2020 15:44:20 -0300 Subject: [PATCH] AArch64: Report tag violation error information 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 * 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 | 9 +++++ gdb/aarch64-linux-tdep.c | 70 ++++++++++++++++++++++++++++++++++++ gdb/arch/aarch64-mte-linux.h | 6 ++++ 3 files changed, 85 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ce3373ba9d..52e0ddeb2b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2021-03-24 Luis Machado + + * 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 * aarch64-linux-tdep.c: Include gdbsupport/selftest.h. diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index e71f062e25..15bbdb253f 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -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 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. */ diff --git a/gdb/arch/aarch64-mte-linux.h b/gdb/arch/aarch64-mte-linux.h index f517638831..2aa97eb861 100644 --- a/gdb/arch/aarch64-mte-linux.h +++ b/gdb/arch/aarch64-mte-linux.h @@ -35,6 +35,12 @@ #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 { -- 2.34.1