diff options
author | Luis Machado <luis.machado@arm.com> | 2022-03-31 11:42:35 +0100 |
---|---|---|
committer | Luis Machado <luis.machado@arm.com> | 2022-07-19 15:24:31 +0100 |
commit | 68cffbbd4406b4efe1aa6e18460b1d7ca02549f1 (patch) | |
tree | f8a61526011db5bf0c60314f38de6fc48cd82ca0 /gdb/memtag.c | |
parent | d0ff5ca959df91dcef16ec57154ff199fad5a4e4 (diff) | |
download | gdb-68cffbbd4406b4efe1aa6e18460b1d7ca02549f1.zip gdb-68cffbbd4406b4efe1aa6e18460b1d7ca02549f1.tar.gz 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/memtag.c')
-rw-r--r-- | gdb/memtag.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/gdb/memtag.c b/gdb/memtag.c new file mode 100644 index 0000000..ca64569 --- /dev/null +++ b/gdb/memtag.c @@ -0,0 +1,68 @@ +/* GDB generic memory tagging functions. + + Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "memtag.h" +#include "bfd.h" + +/* See memtag.h */ + +bool +get_next_core_memtag_section (bfd *abfd, asection *section, + CORE_ADDR address, memtag_section_info &info) +{ + /* If the caller provided no SECTION to start from, search from the + beginning. */ + if (section == nullptr) + section = bfd_get_section_by_name (abfd, "memtag"); + + /* Go through all the memtag sections and figure out if ADDRESS + falls within one of the memory ranges that contain tags. */ + while (section != nullptr) + { + size_t memtag_range_size = section->rawsize; + size_t tags_size = bfd_section_size (section); + + /* Empty memory range or empty tag dump should not happen. Warn about + it but keep going through the sections. */ + if (memtag_range_size == 0 || tags_size == 0) + { + warning (_("Found memtag section with empty memory " + "range or empty tag dump")); + continue; + } + else + { + CORE_ADDR start_address = bfd_section_vma (section); + CORE_ADDR end_address = start_address + memtag_range_size; + + /* Is the address within [start_address, end_address)? */ + if (address >= start_address + && address < end_address) + { + info.start_address = start_address; + info.end_address = end_address; + info.memtag_section = section; + return true; + } + } + section = bfd_get_next_section_by_name (abfd, section); + } + return false; +} |