mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 01:53:38 +08:00
gdb: AArch64: Support MTE on baremetal
This commit moves aarch64_linux_memtag_matches_p, aarch64_linux_set_memtags, aarch64_linux_get_memtag, and aarch64_linux_memtag_to_string hooks (plus the aarch64_mte_get_atag function used by them), along with the setting of the memtag granule size, from aarch64-linux-tdep.c to aarch64-tdep.c, making MTE available on baremetal targets. Since the aarch64-linux-tdep.c layer inherits these hooks from aarch64-tdep.c, there is no effective change for aarch64-linux targets. Helpers used both by aarch64-tdep.c and by aarch64-linux-tdep.c were moved from arch/aarch64-mte-linux.{c,h} to new arch/aarch64-mte.{c,h} files. Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org> Tested-By: Luis Machado <luis.machado@arm.com> Approved-By: Luis Machado <luis.machado@arm.com> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
This commit is contained in:
parent
1d4ed59075
commit
b782c65ba1
@ -746,6 +746,7 @@ ALL_64_TARGET_OBS = \
|
||||
amd64-windows-tdep.o \
|
||||
arch/aarch64.o \
|
||||
arch/aarch64-insn.o \
|
||||
arch/aarch64-mte.o \
|
||||
arch/aarch64-mte-linux.o \
|
||||
arch/aarch64-scalable-linux.o \
|
||||
arch/amd64-linux-tdesc.o \
|
||||
@ -1551,6 +1552,7 @@ HFILES_NO_SRCDIR = \
|
||||
arch/aarch32.h \
|
||||
arch/aarch64.h \
|
||||
arch/aarch64-insn.h \
|
||||
arch/aarch64-mte.h \
|
||||
arch/aarch64-mte-linux.h \
|
||||
arch/aarch64-scalable-linux.h \
|
||||
arch/amd64-linux-tdesc.h \
|
||||
@ -1664,6 +1666,7 @@ ALLDEPFILES = \
|
||||
arch/aarch32.c \
|
||||
arch/aarch64.c \
|
||||
arch/aarch64-insn.c \
|
||||
arch/aarch64-mte.c \
|
||||
arch/aarch64-mte-linux.c \
|
||||
arch/aarch64-scalable-linux.c \
|
||||
arch/amd64.c \
|
||||
|
3
gdb/NEWS
3
gdb/NEWS
@ -17,6 +17,9 @@
|
||||
This may cause breakage when using an incompatible libc, like uclibc or
|
||||
newlib, or an older glibc.
|
||||
|
||||
* MTE (Memory Tagging Extension) debugging is now supported on AArch64 baremetal
|
||||
targets.
|
||||
|
||||
*** Changes in GDB 15
|
||||
|
||||
* The MPX commands "show/set mpx bound" have been deprecated, as Intel
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "record-full.h"
|
||||
#include "linux-record.h"
|
||||
|
||||
#include "arch/aarch64-mte.h"
|
||||
#include "arch/aarch64-mte-linux.h"
|
||||
#include "arch/aarch64-scalable-linux.h"
|
||||
|
||||
@ -2427,29 +2428,6 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
|
||||
return {};
|
||||
}
|
||||
|
||||
/* Helper to get the allocation tag from a 64-bit ADDRESS.
|
||||
|
||||
Return the allocation tag if successful and nullopt otherwise. */
|
||||
|
||||
static std::optional<CORE_ADDR>
|
||||
aarch64_mte_get_atag (CORE_ADDR address)
|
||||
{
|
||||
gdb::byte_vector tags;
|
||||
|
||||
/* Attempt to fetch the allocation tag. */
|
||||
if (!target_fetch_memtags (address, 1, tags,
|
||||
static_cast<int> (memtag_type::allocation)))
|
||||
return {};
|
||||
|
||||
/* Only one tag should've been returned. Make sure we got exactly that. */
|
||||
if (tags.size () != 1)
|
||||
error (_("Target returned an unexpected number of tags."));
|
||||
|
||||
/* Although our tags are 4 bits in size, they are stored in a
|
||||
byte. */
|
||||
return tags[0];
|
||||
}
|
||||
|
||||
/* Implement the tagged_address_p gdbarch method. */
|
||||
|
||||
static bool
|
||||
@ -2466,132 +2444,6 @@ aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Implement the memtag_matches_p gdbarch method. */
|
||||
|
||||
static bool
|
||||
aarch64_linux_memtag_matches_p (struct gdbarch *gdbarch,
|
||||
struct value *address)
|
||||
{
|
||||
gdb_assert (address != nullptr);
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
|
||||
/* Fetch the allocation tag for ADDRESS. */
|
||||
std::optional<CORE_ADDR> atag
|
||||
= aarch64_mte_get_atag (gdbarch_remove_non_address_bits (gdbarch, addr));
|
||||
|
||||
if (!atag.has_value ())
|
||||
return true;
|
||||
|
||||
/* Fetch the logical tag for ADDRESS. */
|
||||
gdb_byte ltag = aarch64_mte_get_ltag (addr);
|
||||
|
||||
/* Are the tags the same? */
|
||||
return ltag == *atag;
|
||||
}
|
||||
|
||||
/* Implement the set_memtags gdbarch method. */
|
||||
|
||||
static bool
|
||||
aarch64_linux_set_memtags (struct gdbarch *gdbarch, struct value *address,
|
||||
size_t length, const gdb::byte_vector &tags,
|
||||
memtag_type tag_type)
|
||||
{
|
||||
gdb_assert (!tags.empty ());
|
||||
gdb_assert (address != nullptr);
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
|
||||
/* Set the logical tag or the allocation tag. */
|
||||
if (tag_type == memtag_type::logical)
|
||||
{
|
||||
/* When setting logical tags, we don't care about the length, since
|
||||
we are only setting a single logical tag. */
|
||||
addr = aarch64_mte_set_ltag (addr, tags[0]);
|
||||
|
||||
/* Update the value's content with the tag. */
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
gdb_byte *srcbuf = address->contents_raw ().data ();
|
||||
store_unsigned_integer (srcbuf, sizeof (addr), byte_order, addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove the top byte. */
|
||||
addr = gdbarch_remove_non_address_bits (gdbarch, addr);
|
||||
|
||||
/* With G being the number of tag granules and N the number of tags
|
||||
passed in, we can have the following cases:
|
||||
|
||||
1 - G == N: Store all the N tags to memory.
|
||||
|
||||
2 - G < N : Warn about having more tags than granules, but write G
|
||||
tags.
|
||||
|
||||
3 - G > N : This is a "fill tags" operation. We should use the tags
|
||||
as a pattern to fill the granules repeatedly until we have
|
||||
written G tags to memory.
|
||||
*/
|
||||
|
||||
size_t g = aarch64_mte_get_tag_granules (addr, length,
|
||||
AARCH64_MTE_GRANULE_SIZE);
|
||||
size_t n = tags.size ();
|
||||
|
||||
if (g < n)
|
||||
warning (_("Got more tags than memory granules. Tags will be "
|
||||
"truncated."));
|
||||
else if (g > n)
|
||||
warning (_("Using tag pattern to fill memory range."));
|
||||
|
||||
if (!target_store_memtags (addr, length, tags,
|
||||
static_cast<int> (memtag_type::allocation)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Implement the get_memtag gdbarch method. */
|
||||
|
||||
static struct value *
|
||||
aarch64_linux_get_memtag (struct gdbarch *gdbarch, struct value *address,
|
||||
memtag_type tag_type)
|
||||
{
|
||||
gdb_assert (address != nullptr);
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
CORE_ADDR tag = 0;
|
||||
|
||||
/* Get the logical tag or the allocation tag. */
|
||||
if (tag_type == memtag_type::logical)
|
||||
tag = aarch64_mte_get_ltag (addr);
|
||||
else
|
||||
{
|
||||
/* Remove the top byte. */
|
||||
addr = gdbarch_remove_non_address_bits (gdbarch, addr);
|
||||
std::optional<CORE_ADDR> atag = aarch64_mte_get_atag (addr);
|
||||
|
||||
if (!atag.has_value ())
|
||||
return nullptr;
|
||||
|
||||
tag = *atag;
|
||||
}
|
||||
|
||||
/* Convert the tag to a value. */
|
||||
return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
|
||||
tag);
|
||||
}
|
||||
|
||||
/* Implement the memtag_to_string gdbarch method. */
|
||||
|
||||
static std::string
|
||||
aarch64_linux_memtag_to_string (struct gdbarch *gdbarch, struct value *tag_value)
|
||||
{
|
||||
if (tag_value == nullptr)
|
||||
return "";
|
||||
|
||||
CORE_ADDR tag = value_as_address (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. */
|
||||
@ -2900,24 +2752,6 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
/* Register a hook for checking if an address is tagged or not. */
|
||||
set_gdbarch_tagged_address_p (gdbarch, aarch64_linux_tagged_address_p);
|
||||
|
||||
/* Register a hook for checking if there is a memory tag match. */
|
||||
set_gdbarch_memtag_matches_p (gdbarch,
|
||||
aarch64_linux_memtag_matches_p);
|
||||
|
||||
/* Register a hook for setting the logical/allocation tags for
|
||||
a range of addresses. */
|
||||
set_gdbarch_set_memtags (gdbarch, aarch64_linux_set_memtags);
|
||||
|
||||
/* Register a hook for extracting the logical/allocation tag from an
|
||||
address. */
|
||||
set_gdbarch_get_memtag (gdbarch, aarch64_linux_get_memtag);
|
||||
|
||||
/* Set the allocation tag granule size to 16 bytes. */
|
||||
set_gdbarch_memtag_granule_size (gdbarch, AARCH64_MTE_GRANULE_SIZE);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#include "aarch64-tdep.h"
|
||||
#include "aarch64-ravenscar-thread.h"
|
||||
#include "arch/aarch64-mte.h"
|
||||
|
||||
#include "record.h"
|
||||
#include "record-full.h"
|
||||
@ -4088,6 +4089,156 @@ aarch64_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
|
||||
return streq (inst.opcode->name, "ret");
|
||||
}
|
||||
|
||||
/* Helper to get the allocation tag from a 64-bit ADDRESS.
|
||||
|
||||
Return the allocation tag if successful and nullopt otherwise. */
|
||||
|
||||
std::optional<CORE_ADDR>
|
||||
aarch64_mte_get_atag (CORE_ADDR address)
|
||||
{
|
||||
gdb::byte_vector tags;
|
||||
|
||||
/* Attempt to fetch the allocation tag. */
|
||||
if (!target_fetch_memtags (address, 1, tags,
|
||||
static_cast<int> (memtag_type::allocation)))
|
||||
return {};
|
||||
|
||||
/* Only one tag should've been returned. Make sure we got exactly that. */
|
||||
if (tags.size () != 1)
|
||||
error (_("Target returned an unexpected number of tags."));
|
||||
|
||||
/* Although our tags are 4 bits in size, they are stored in a
|
||||
byte. */
|
||||
return tags[0];
|
||||
}
|
||||
|
||||
/* Implement the memtag_matches_p gdbarch method. */
|
||||
|
||||
static bool
|
||||
aarch64_memtag_matches_p (struct gdbarch *gdbarch,
|
||||
struct value *address)
|
||||
{
|
||||
gdb_assert (address != nullptr);
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
|
||||
/* Fetch the allocation tag for ADDRESS. */
|
||||
std::optional<CORE_ADDR> atag
|
||||
= aarch64_mte_get_atag (gdbarch_remove_non_address_bits (gdbarch, addr));
|
||||
|
||||
if (!atag.has_value ())
|
||||
return true;
|
||||
|
||||
/* Fetch the logical tag for ADDRESS. */
|
||||
gdb_byte ltag = aarch64_mte_get_ltag (addr);
|
||||
|
||||
/* Are the tags the same? */
|
||||
return ltag == *atag;
|
||||
}
|
||||
|
||||
/* Implement the set_memtags gdbarch method. */
|
||||
|
||||
static bool
|
||||
aarch64_set_memtags (struct gdbarch *gdbarch, struct value *address,
|
||||
size_t length, const gdb::byte_vector &tags,
|
||||
memtag_type tag_type)
|
||||
{
|
||||
gdb_assert (!tags.empty ());
|
||||
gdb_assert (address != nullptr);
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
|
||||
/* Set the logical tag or the allocation tag. */
|
||||
if (tag_type == memtag_type::logical)
|
||||
{
|
||||
/* When setting logical tags, we don't care about the length, since
|
||||
we are only setting a single logical tag. */
|
||||
addr = aarch64_mte_set_ltag (addr, tags[0]);
|
||||
|
||||
/* Update the value's content with the tag. */
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
gdb_byte *srcbuf = address->contents_raw ().data ();
|
||||
store_unsigned_integer (srcbuf, sizeof (addr), byte_order, addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove the top byte. */
|
||||
addr = gdbarch_remove_non_address_bits (gdbarch, addr);
|
||||
|
||||
/* With G being the number of tag granules and N the number of tags
|
||||
passed in, we can have the following cases:
|
||||
|
||||
1 - G == N: Store all the N tags to memory.
|
||||
|
||||
2 - G < N : Warn about having more tags than granules, but write G
|
||||
tags.
|
||||
|
||||
3 - G > N : This is a "fill tags" operation. We should use the tags
|
||||
as a pattern to fill the granules repeatedly until we have
|
||||
written G tags to memory.
|
||||
*/
|
||||
|
||||
size_t g = aarch64_mte_get_tag_granules (addr, length,
|
||||
AARCH64_MTE_GRANULE_SIZE);
|
||||
size_t n = tags.size ();
|
||||
|
||||
if (g < n)
|
||||
warning (_("Got more tags than memory granules. Tags will be "
|
||||
"truncated."));
|
||||
else if (g > n)
|
||||
warning (_("Using tag pattern to fill memory range."));
|
||||
|
||||
if (!target_store_memtags (addr, length, tags,
|
||||
static_cast<int> (memtag_type::allocation)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Implement the get_memtag gdbarch method. */
|
||||
|
||||
static struct value *
|
||||
aarch64_get_memtag (struct gdbarch *gdbarch, struct value *address,
|
||||
memtag_type tag_type)
|
||||
{
|
||||
gdb_assert (address != nullptr);
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
CORE_ADDR tag = 0;
|
||||
|
||||
/* Get the logical tag or the allocation tag. */
|
||||
if (tag_type == memtag_type::logical)
|
||||
tag = aarch64_mte_get_ltag (addr);
|
||||
else
|
||||
{
|
||||
/* Remove the top byte. */
|
||||
addr = gdbarch_remove_non_address_bits (gdbarch, addr);
|
||||
std::optional<CORE_ADDR> atag = aarch64_mte_get_atag (addr);
|
||||
|
||||
if (!atag.has_value ())
|
||||
return nullptr;
|
||||
|
||||
tag = *atag;
|
||||
}
|
||||
|
||||
/* Convert the tag to a value. */
|
||||
return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
|
||||
tag);
|
||||
}
|
||||
|
||||
/* Implement the memtag_to_string gdbarch method. */
|
||||
|
||||
static std::string
|
||||
aarch64_memtag_to_string (struct gdbarch *gdbarch, struct value *tag_value)
|
||||
{
|
||||
if (tag_value == nullptr)
|
||||
return "";
|
||||
|
||||
CORE_ADDR tag = value_as_address (tag_value);
|
||||
|
||||
return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
|
||||
}
|
||||
|
||||
/* AArch64 implementation of the remove_non_address_bits gdbarch hook. Remove
|
||||
non address bits from a pointer value. */
|
||||
|
||||
@ -4504,6 +4655,23 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
aarch64_pseudo_register_reggroup_p);
|
||||
set_gdbarch_cannot_store_register (gdbarch, aarch64_cannot_store_register);
|
||||
|
||||
/* Set the allocation tag granule size to 16 bytes. */
|
||||
set_gdbarch_memtag_granule_size (gdbarch, AARCH64_MTE_GRANULE_SIZE);
|
||||
|
||||
/* Register a hook for checking if there is a memory tag match. */
|
||||
set_gdbarch_memtag_matches_p (gdbarch, aarch64_memtag_matches_p);
|
||||
|
||||
/* Register a hook for setting the logical/allocation tags for
|
||||
a range of addresses. */
|
||||
set_gdbarch_set_memtags (gdbarch, aarch64_set_memtags);
|
||||
|
||||
/* Register a hook for extracting the logical/allocation tag from an
|
||||
address. */
|
||||
set_gdbarch_get_memtag (gdbarch, aarch64_get_memtag);
|
||||
|
||||
/* Register a hook for converting a memory tag to a string. */
|
||||
set_gdbarch_memtag_to_string (gdbarch, aarch64_memtag_to_string);
|
||||
|
||||
/* ABI */
|
||||
set_gdbarch_short_bit (gdbarch, 16);
|
||||
set_gdbarch_int_bit (gdbarch, 32);
|
||||
|
@ -203,4 +203,6 @@ void aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
|
||||
|
||||
bool aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch);
|
||||
|
||||
std::optional<CORE_ADDR> aarch64_mte_get_atag (CORE_ADDR address);
|
||||
|
||||
#endif /* aarch64-tdep.h */
|
||||
|
@ -75,59 +75,3 @@ aarch64_mte_unpack_tags (gdb::byte_vector &tags, bool skip_first)
|
||||
tags = std::move (unpacked_tags);
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte-linux.h */
|
||||
|
||||
size_t
|
||||
aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len, size_t granule_size)
|
||||
{
|
||||
/* An empty range has 0 tag granules. */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* Start address */
|
||||
CORE_ADDR s_addr = align_down (addr, granule_size);
|
||||
/* End address */
|
||||
CORE_ADDR e_addr = align_down (addr + len - 1, granule_size);
|
||||
|
||||
/* We always have at least 1 granule because len is non-zero at this
|
||||
point. */
|
||||
return 1 + (e_addr - s_addr) / granule_size;
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte-linux.h */
|
||||
|
||||
CORE_ADDR
|
||||
aarch64_mte_make_ltag_bits (CORE_ADDR value)
|
||||
{
|
||||
return value & AARCH64_MTE_LOGICAL_MAX_VALUE;
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte-linux.h */
|
||||
|
||||
CORE_ADDR
|
||||
aarch64_mte_make_ltag (CORE_ADDR value)
|
||||
{
|
||||
return (aarch64_mte_make_ltag_bits (value)
|
||||
<< AARCH64_MTE_LOGICAL_TAG_START_BIT);
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte-linux.h */
|
||||
|
||||
CORE_ADDR
|
||||
aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag)
|
||||
{
|
||||
/* Remove the existing tag. */
|
||||
address &= ~aarch64_mte_make_ltag (AARCH64_MTE_LOGICAL_MAX_VALUE);
|
||||
|
||||
/* Return the new tagged address. */
|
||||
return address | aarch64_mte_make_ltag (tag);
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte-linux.h */
|
||||
|
||||
CORE_ADDR
|
||||
aarch64_mte_get_ltag (CORE_ADDR address)
|
||||
{
|
||||
CORE_ADDR ltag_addr = address >> AARCH64_MTE_LOGICAL_TAG_START_BIT;
|
||||
return aarch64_mte_make_ltag_bits (ltag_addr);
|
||||
}
|
||||
|
@ -29,12 +29,6 @@
|
||||
/* The MTE regset consists of a single 64-bit register. */
|
||||
#define AARCH64_LINUX_SIZEOF_MTE 8
|
||||
|
||||
/* We have one tag per 16 bytes of memory. */
|
||||
#define AARCH64_MTE_GRANULE_SIZE 16
|
||||
#define AARCH64_MTE_TAG_BIT_SIZE 4
|
||||
#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
|
||||
@ -50,27 +44,6 @@ enum class aarch64_memtag_type
|
||||
mte_allocation
|
||||
};
|
||||
|
||||
/* Return the number of tag granules in the memory range
|
||||
[ADDR, ADDR + LEN) given GRANULE_SIZE. */
|
||||
extern size_t aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len,
|
||||
size_t granule_size);
|
||||
|
||||
/* Return the 4-bit tag made from VALUE. */
|
||||
extern CORE_ADDR aarch64_mte_make_ltag_bits (CORE_ADDR value);
|
||||
|
||||
/* Return the 4-bit tag that can be OR-ed to an address. */
|
||||
extern CORE_ADDR aarch64_mte_make_ltag (CORE_ADDR value);
|
||||
|
||||
/* Helper to set the logical TAG for a 64-bit ADDRESS.
|
||||
|
||||
It is always possible to set the logical tag. */
|
||||
extern CORE_ADDR aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag);
|
||||
|
||||
/* Helper to get the logical tag from a 64-bit ADDRESS.
|
||||
|
||||
It is always possible to get the logical tag. */
|
||||
extern CORE_ADDR aarch64_mte_get_ltag (CORE_ADDR address);
|
||||
|
||||
/* Given a TAGS vector containing 1 MTE tag per byte, pack the data as
|
||||
2 tags per byte and resize the vector. */
|
||||
extern void aarch64_mte_pack_tags (gdb::byte_vector &tags);
|
||||
|
77
gdb/arch/aarch64-mte.c
Normal file
77
gdb/arch/aarch64-mte.c
Normal file
@ -0,0 +1,77 @@
|
||||
/* Common AArch64 functionality for MTE
|
||||
|
||||
Copyright (C) 2021-2024 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 "arch/aarch64-mte.h"
|
||||
|
||||
/* See arch/aarch64-mte.h */
|
||||
|
||||
size_t
|
||||
aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len, size_t granule_size)
|
||||
{
|
||||
/* An empty range has 0 tag granules. */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* Start address */
|
||||
CORE_ADDR s_addr = align_down (addr, granule_size);
|
||||
/* End address */
|
||||
CORE_ADDR e_addr = align_down (addr + len - 1, granule_size);
|
||||
|
||||
/* We always have at least 1 granule because len is non-zero at this
|
||||
point. */
|
||||
return 1 + (e_addr - s_addr) / granule_size;
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte.h */
|
||||
|
||||
CORE_ADDR
|
||||
aarch64_mte_make_ltag_bits (CORE_ADDR value)
|
||||
{
|
||||
return value & AARCH64_MTE_LOGICAL_MAX_VALUE;
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte.h */
|
||||
|
||||
CORE_ADDR
|
||||
aarch64_mte_make_ltag (CORE_ADDR value)
|
||||
{
|
||||
return (aarch64_mte_make_ltag_bits (value)
|
||||
<< AARCH64_MTE_LOGICAL_TAG_START_BIT);
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte.h */
|
||||
|
||||
CORE_ADDR
|
||||
aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag)
|
||||
{
|
||||
/* Remove the existing tag. */
|
||||
address &= ~aarch64_mte_make_ltag (AARCH64_MTE_LOGICAL_MAX_VALUE);
|
||||
|
||||
/* Return the new tagged address. */
|
||||
return address | aarch64_mte_make_ltag (tag);
|
||||
}
|
||||
|
||||
/* See arch/aarch64-mte.h */
|
||||
|
||||
CORE_ADDR
|
||||
aarch64_mte_get_ltag (CORE_ADDR address)
|
||||
{
|
||||
CORE_ADDR ltag_addr = address >> AARCH64_MTE_LOGICAL_TAG_START_BIT;
|
||||
return aarch64_mte_make_ltag_bits (ltag_addr);
|
||||
}
|
51
gdb/arch/aarch64-mte.h
Normal file
51
gdb/arch/aarch64-mte.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* Common AArch64 definitions for MTE
|
||||
|
||||
Copyright (C) 2021-2024 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/>. */
|
||||
|
||||
#ifndef ARCH_AARCH64_MTE_H
|
||||
#define ARCH_AARCH64_MTE_H
|
||||
|
||||
|
||||
/* We have one tag per 16 bytes of memory. */
|
||||
#define AARCH64_MTE_GRANULE_SIZE 16
|
||||
#define AARCH64_MTE_TAG_BIT_SIZE 4
|
||||
#define AARCH64_MTE_LOGICAL_TAG_START_BIT 56
|
||||
#define AARCH64_MTE_LOGICAL_MAX_VALUE 0xf
|
||||
|
||||
/* Return the number of tag granules in the memory range
|
||||
[ADDR, ADDR + LEN) given GRANULE_SIZE. */
|
||||
extern size_t aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len,
|
||||
size_t granule_size);
|
||||
|
||||
/* Return the 4-bit tag made from VALUE. */
|
||||
extern CORE_ADDR aarch64_mte_make_ltag_bits (CORE_ADDR value);
|
||||
|
||||
/* Return the 4-bit tag that can be OR-ed to an address. */
|
||||
extern CORE_ADDR aarch64_mte_make_ltag (CORE_ADDR value);
|
||||
|
||||
/* Helper to set the logical TAG for a 64-bit ADDRESS.
|
||||
|
||||
It is always possible to set the logical tag. */
|
||||
extern CORE_ADDR aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag);
|
||||
|
||||
/* Helper to get the logical tag from a 64-bit ADDRESS.
|
||||
|
||||
It is always possible to get the logical tag. */
|
||||
extern CORE_ADDR aarch64_mte_get_ltag (CORE_ADDR address);
|
||||
|
||||
#endif /* ARCH_AARCH64_MTE_H */
|
@ -59,7 +59,8 @@ amd64_tobjs="ravenscar-thread.o amd64-ravenscar-thread.o \
|
||||
case "${targ}" in
|
||||
aarch64*-*-*)
|
||||
cpu_obs="aarch32-tdep.o aarch64-tdep.o arch/aarch32.o \
|
||||
arch/aarch64-insn.o arch/aarch64.o ravenscar-thread.o \
|
||||
arch/aarch64-insn.o arch/aarch64.o arch/aarch64-mte.o \
|
||||
ravenscar-thread.o \
|
||||
aarch64-ravenscar-thread.o";;
|
||||
|
||||
alpha*-*-*)
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "linux-ptrace.h"
|
||||
|
||||
#include "arch/aarch64.h"
|
||||
#include "arch/aarch64-mte.h"
|
||||
#include "arch/aarch64-mte-linux.h"
|
||||
#include "nat/aarch64-linux.h"
|
||||
#include "nat/aarch64-mte-linux-ptrace.h"
|
||||
|
@ -48,6 +48,7 @@ case "${gdbserver_host}" in
|
||||
srv_tgtobj="$srv_tgtobj nat/aarch64-linux.o"
|
||||
srv_tgtobj="$srv_tgtobj arch/aarch64-insn.o"
|
||||
srv_tgtobj="$srv_tgtobj arch/aarch64.o"
|
||||
srv_tgtobj="$srv_tgtobj arch/aarch64-mte.o"
|
||||
srv_tgtobj="$srv_tgtobj arch/aarch64-mte-linux.o"
|
||||
srv_tgtobj="$srv_tgtobj arch/aarch64-scalable-linux.o"
|
||||
srv_tgtobj="$srv_tgtobj linux-aarch64-tdesc.o"
|
||||
|
Loading…
Reference in New Issue
Block a user