binutils-gdb/gdb/testsuite/gdb.arch/aarch64-mte.c
Luis Machado bf0aecce6e Add memory tagging testcases
Add an AArch64-specific test and a more generic memory tagging test that
other architectures can run.

Even though architectures not supporting memory tagging can run the memory
tagging tests, the runtime check will make the tests bail out early, as it
would make no sense to proceed without proper support.

It is also tricky to do any further runtime tests for memory tagging, given
we'd need to deal with tags, and those are arch-specific.  Therefore the
test in gdb.base is more of a smoke test.

If an architecture wants to implement memory tagging, then it makes sense to
have tests within gdb.arch instead.

gdb/testsuite/ChangeLog:

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

	* gdb.arch/aarch64-mte.c: New file.
	* gdb.arch/aarch64-mte.exp: New test.
	* gdb.base/memtag.c: New file.
	* gdb.base/memtag.exp: New test.
	* lib/gdb.exp (supports_memtag): New function.
2021-03-24 15:09:59 -03:00

108 lines
3.2 KiB
C

/* This test program is part of GDB, the GNU debugger.
Copyright 2021 Free Software Foundation, Inc.
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/>. */
/* Exercise AArch64's Memory Tagging Extension with tagged pointers. */
/* This test was based on the documentation for the AArch64 Memory Tagging
Extension from the Linux Kernel, found in the sources in
Documentation/arm64/memory-tagging-extension.rst. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/auxv.h>
#include <sys/mman.h>
#include <sys/prctl.h>
/* From arch/arm64/include/uapi/asm/hwcap.h */
#define HWCAP2_MTE (1 << 18)
/* From arch/arm64/include/uapi/asm/mman.h */
#define PROT_MTE 0x20
/* From include/uapi/linux/prctl.h */
#define PR_SET_TAGGED_ADDR_CTRL 55
#define PR_GET_TAGGED_ADDR_CTRL 56
#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
#define PR_MTE_TCF_SHIFT 1
#define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
#define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
#define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
#define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
#define PR_MTE_TAG_SHIFT 3
#define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
void
access_memory (unsigned char *tagged_ptr, unsigned char *untagged_ptr)
{
tagged_ptr[0] = 'a';
}
int
main (int argc, char **argv)
{
unsigned char *tagged_ptr;
unsigned char *untagged_ptr;
unsigned long page_sz = sysconf (_SC_PAGESIZE);
unsigned long hwcap2 = getauxval(AT_HWCAP2);
/* Bail out if MTE is not supported. */
if (!(hwcap2 & HWCAP2_MTE))
return 1;
/* Enable the tagged address ABI, synchronous MTE tag check faults and
allow all non-zero tags in the randomly generated set. */
if (prctl (PR_SET_TAGGED_ADDR_CTRL,
PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC
| (0xfffe << PR_MTE_TAG_SHIFT),
0, 0, 0))
{
perror ("prctl () failed");
return 1;
}
/* Create a mapping that will have PROT_MTE set. */
tagged_ptr = mmap (0, page_sz, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (tagged_ptr == MAP_FAILED)
{
perror ("mmap () failed");
return 1;
}
/* Create another mapping that won't have PROT_MTE set. */
untagged_ptr = mmap (0, page_sz, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (untagged_ptr == MAP_FAILED)
{
perror ("mmap () failed");
return 1;
}
/* Enable MTE on the above anonymous mmap. */
if (mprotect (tagged_ptr, page_sz, PROT_READ | PROT_WRITE | PROT_MTE))
{
perror ("mprotect () failed");
return 1;
}
access_memory (tagged_ptr, untagged_ptr);
return 0;
}