aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbarch.c
diff options
context:
space:
mode:
authorLuis Machado <luis.machado@arm.com>2022-03-31 11:42:35 +0100
committerLuis Machado <luis.machado@arm.com>2022-07-19 15:24:31 +0100
commit68cffbbd4406b4efe1aa6e18460b1d7ca02549f1 (patch)
treef8a61526011db5bf0c60314f38de6fc48cd82ca0 /gdb/gdbarch.c
parentd0ff5ca959df91dcef16ec57154ff199fad5a4e4 (diff)
downloadfsf-binutils-gdb-68cffbbd4406b4efe1aa6e18460b1d7ca02549f1.zip
fsf-binutils-gdb-68cffbbd4406b4efe1aa6e18460b1d7ca02549f1.tar.gz
fsf-binutils-gdb-68cffbbd4406b4efe1aa6e18460b1d7ca02549f1.tar.bz2
[AArch64] MTE corefile support
Teach GDB how to dump memory tags for AArch64 when using the gcore command and how to read memory tag data back from a core file generated by GDB (via gcore) or by the Linux kernel. The format is documented in the Linux Kernel documentation [1]. Each tagged memory range (listed in /proc/<pid>/smaps) gets dumped to its own PT_AARCH64_MEMTAG_MTE segment. A section named ".memtag" is created for each of those segments when reading the core file back. To save a little bit of space, given MTE tags only take 4 bits, the memory tags are stored packed as 2 tags per byte. When reading the data back, the tags are unpacked. I've added a new testcase to exercise the feature. Build-tested with --enable-targets=all and regression tested on aarch64-linux Ubuntu 20.04. [1] Documentation/arm64/memory-tagging-extension.rst (Core Dump Support)
Diffstat (limited to 'gdb/gdbarch.c')
-rw-r--r--gdb/gdbarch.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 68ef048..5d14aec 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -171,6 +171,9 @@ struct gdbarch
gdbarch_iterate_over_regset_sections_ftype *iterate_over_regset_sections;
gdbarch_make_corefile_notes_ftype *make_corefile_notes;
gdbarch_find_memory_regions_ftype *find_memory_regions;
+ gdbarch_create_memtag_section_ftype *create_memtag_section;
+ gdbarch_fill_memtag_section_ftype *fill_memtag_section;
+ gdbarch_decode_memtag_section_ftype *decode_memtag_section;
gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries;
gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix;
gdbarch_core_pid_to_str_ftype *core_pid_to_str;
@@ -527,6 +530,9 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of iterate_over_regset_sections, has predicate. */
/* Skip verify of make_corefile_notes, has predicate. */
/* Skip verify of find_memory_regions, has predicate. */
+ /* Skip verify of create_memtag_section, has predicate. */
+ /* Skip verify of fill_memtag_section, has predicate. */
+ /* Skip verify of decode_memtag_section, has predicate. */
/* Skip verify of core_xfer_shared_libraries, has predicate. */
/* Skip verify of core_xfer_shared_libraries_aix, has predicate. */
/* Skip verify of core_pid_to_str, has predicate. */
@@ -1097,6 +1103,24 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: find_memory_regions = <%s>\n",
host_address_to_string (gdbarch->find_memory_regions));
gdb_printf (file,
+ "gdbarch_dump: gdbarch_create_memtag_section_p() = %d\n",
+ gdbarch_create_memtag_section_p (gdbarch));
+ gdb_printf (file,
+ "gdbarch_dump: create_memtag_section = <%s>\n",
+ host_address_to_string (gdbarch->create_memtag_section));
+ gdb_printf (file,
+ "gdbarch_dump: gdbarch_fill_memtag_section_p() = %d\n",
+ gdbarch_fill_memtag_section_p (gdbarch));
+ gdb_printf (file,
+ "gdbarch_dump: fill_memtag_section = <%s>\n",
+ host_address_to_string (gdbarch->fill_memtag_section));
+ gdb_printf (file,
+ "gdbarch_dump: gdbarch_decode_memtag_section_p() = %d\n",
+ gdbarch_decode_memtag_section_p (gdbarch));
+ gdb_printf (file,
+ "gdbarch_dump: decode_memtag_section = <%s>\n",
+ host_address_to_string (gdbarch->decode_memtag_section));
+ gdb_printf (file,
"gdbarch_dump: gdbarch_core_xfer_shared_libraries_p() = %d\n",
gdbarch_core_xfer_shared_libraries_p (gdbarch));
gdb_printf (file,
@@ -3745,6 +3769,78 @@ set_gdbarch_find_memory_regions (struct gdbarch *gdbarch,
}
bool
+gdbarch_create_memtag_section_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->create_memtag_section != NULL;
+}
+
+asection *
+gdbarch_create_memtag_section (struct gdbarch *gdbarch, bfd *obfd, CORE_ADDR address, size_t size)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->create_memtag_section != NULL);
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_create_memtag_section called\n");
+ return gdbarch->create_memtag_section (gdbarch, obfd, address, size);
+}
+
+void
+set_gdbarch_create_memtag_section (struct gdbarch *gdbarch,
+ gdbarch_create_memtag_section_ftype create_memtag_section)
+{
+ gdbarch->create_memtag_section = create_memtag_section;
+}
+
+bool
+gdbarch_fill_memtag_section_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->fill_memtag_section != NULL;
+}
+
+bool
+gdbarch_fill_memtag_section (struct gdbarch *gdbarch, asection *osec)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->fill_memtag_section != NULL);
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_fill_memtag_section called\n");
+ return gdbarch->fill_memtag_section (gdbarch, osec);
+}
+
+void
+set_gdbarch_fill_memtag_section (struct gdbarch *gdbarch,
+ gdbarch_fill_memtag_section_ftype fill_memtag_section)
+{
+ gdbarch->fill_memtag_section = fill_memtag_section;
+}
+
+bool
+gdbarch_decode_memtag_section_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->decode_memtag_section != NULL;
+}
+
+gdb::byte_vector
+gdbarch_decode_memtag_section (struct gdbarch *gdbarch, bfd_section *section, int type, CORE_ADDR address, size_t length)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->decode_memtag_section != NULL);
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_decode_memtag_section called\n");
+ return gdbarch->decode_memtag_section (gdbarch, section, type, address, length);
+}
+
+void
+set_gdbarch_decode_memtag_section (struct gdbarch *gdbarch,
+ gdbarch_decode_memtag_section_ftype decode_memtag_section)
+{
+ gdbarch->decode_memtag_section = decode_memtag_section;
+}
+
+bool
gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);