mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 09:08:59 +00:00
Add gdbarch hooks to detect and return tagged addresses
This patch adds a couple gdbarch hooks: gdbarch_tagged_address_p checks if a particular address is tagged or not. gdbarch_address_tag returns the tag for a particular address, if tagged. I've used struct value as opposed to straight CORE_ADDR so other architectures can use the infrastructure without having to rely on fixed types. gdb/ChangeLog: YYYY-MM-DD Luis Machado <luis.machado@linaro.org> * aarch64-linux-tdep.c: Include target.h, arch-utils.h, value.h and arch/aarch64-linux.h. (make_ltag_bits, make_ltag, aarch64_linux_set_ltag) (aarch64_linux_get_ltag, aarch64_linux_get_atag) (value_valid_for_memtag, aarch64_linux_tagged_address_p) (aarch64_linux_memtag_mismatch_p, aarch64_linux_set_memtags) (aarch64_linux_get_memtag, aarch64_linux_memtag_to_string): New functions. (aarch64_linux_init_abi): Initialize MTE-related gdbarch hooks. * arch-utils.c (default_memtag_to_string, +default_tagged_address_p) (default_memtag_mismatch_p, default_set_memtags) (default_get_memtag): New functions. * arch-utils.h (default_memtag_to_string, default_tagged_address_p) (default_memtag_mismatch_p, default_set_memtags) (default_get_memtag): New prototypes. * arch/aarch64-linux.h (MTE_LOGICAL_TAG_START_BIT): Define. (MTE_LOGICAL_MAX_VALUE): Define. * gdbarch.c: Regenerate. * gdbarch.h: Regenerate. * gdbarch.sh (memtag_to_string, tagged_address_p, memtag_mismatch_p) (set_memtags, get_memtag, memtag_granule_size): New gdbarch hooks. (enum memtag_type): New enum.
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include "symtab.h"
|
||||
#include "tramp-frame.h"
|
||||
#include "trad-frame.h"
|
||||
#include "target.h"
|
||||
#include "target/target.h"
|
||||
|
||||
#include "regcache.h"
|
||||
@@ -46,6 +47,11 @@
|
||||
|
||||
#include "arch/aarch64-linux.h"
|
||||
|
||||
#include "arch-utils.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "arch/aarch64-linux.h"
|
||||
|
||||
/* Signal frame handling.
|
||||
|
||||
+------------+ ^
|
||||
@@ -1457,6 +1463,241 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
|
||||
return {};
|
||||
}
|
||||
|
||||
/* Return the 4-bit tag made from VALUE. */
|
||||
|
||||
static CORE_ADDR
|
||||
make_ltag_bits (CORE_ADDR value)
|
||||
{
|
||||
return value & MTE_LOGICAL_MAX_VALUE;
|
||||
}
|
||||
|
||||
/* Return the 4-bit tag that can be OR-ed to an address. */
|
||||
|
||||
static CORE_ADDR
|
||||
make_ltag (CORE_ADDR value)
|
||||
{
|
||||
return make_ltag_bits (value) << MTE_LOGICAL_TAG_START_BIT;
|
||||
}
|
||||
|
||||
/* Helper to set the logical TAG for a 64-bit ADDRESS.
|
||||
|
||||
It is always possible to set the logical tag. */
|
||||
|
||||
static CORE_ADDR
|
||||
aarch64_linux_set_ltag (CORE_ADDR address, CORE_ADDR tag)
|
||||
{
|
||||
/* Remove the existing tag. */
|
||||
address &= ~make_ltag (MTE_LOGICAL_MAX_VALUE);
|
||||
|
||||
/* Return the new tagged address. */
|
||||
return address | make_ltag (tag);
|
||||
}
|
||||
|
||||
/* Helper to get the logical tag from a 64-bit ADDRESS.
|
||||
|
||||
It is always possible to get the logical tag. */
|
||||
|
||||
static CORE_ADDR
|
||||
aarch64_linux_get_ltag (CORE_ADDR address)
|
||||
{
|
||||
return make_ltag_bits (address >> MTE_LOGICAL_TAG_START_BIT);
|
||||
}
|
||||
|
||||
/* Helper to get the allocation tag from a 64-bit ADDRESS.
|
||||
|
||||
Return 0 for success and non-zero otherwise. */
|
||||
|
||||
static int
|
||||
aarch64_linux_get_atag (CORE_ADDR address, CORE_ADDR *tag)
|
||||
{
|
||||
gdb::byte_vector tags;
|
||||
|
||||
/* Attempt to fetch the allocation tag. */
|
||||
if (target_fetch_memtags (address, 0, tags) != 0)
|
||||
return 1;
|
||||
|
||||
/* Empty tag vector is an error. */
|
||||
if (tags.empty ())
|
||||
return 1;
|
||||
|
||||
/* Although our tags are 4 bits in size, they are stored in a
|
||||
byte. */
|
||||
*tag = tags[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper to validate VALUE for a memtag operation. */
|
||||
|
||||
static bool
|
||||
value_valid_for_memtag (struct value *value)
|
||||
{
|
||||
if (value != nullptr && VALUE_LVAL (value) == not_lval
|
||||
&& value_contents_raw (value) != nullptr)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Implement the tagged_address_p gdbarch method. */
|
||||
|
||||
static bool
|
||||
aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
|
||||
{
|
||||
if (!value_valid_for_memtag (address))
|
||||
return false;
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
|
||||
/* Check if the page that contains ADDRESS is mapped with PROT_MTE. */
|
||||
if (!linux_address_in_memtag_page (addr))
|
||||
return false;
|
||||
|
||||
/* We have a valid tag in the top byte of the 64-bit address. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Implement the memtag_mismatch_p gdbarch method. */
|
||||
|
||||
static bool
|
||||
aarch64_linux_memtag_mismatch_p (struct gdbarch *gdbarch,
|
||||
struct value *address)
|
||||
{
|
||||
if (!value_valid_for_memtag (address))
|
||||
return false;
|
||||
|
||||
/* Make sure we are dealing with a tagged address to begin with. */
|
||||
if (!aarch64_linux_tagged_address_p (gdbarch, address))
|
||||
return false;
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
|
||||
/* Fetch the allocation tag for ADDRESS. */
|
||||
CORE_ADDR atag = 0;
|
||||
|
||||
if (aarch64_linux_get_atag (addr, &atag) != 0)
|
||||
return false;
|
||||
|
||||
/* Fetch the logical tag for ADDRESS. */
|
||||
gdb_byte ltag = aarch64_linux_get_ltag (addr);
|
||||
|
||||
/* Are the tags the same? */
|
||||
if (ltag == atag)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Implement the set_memtags gdbarch method. */
|
||||
|
||||
static int
|
||||
aarch64_linux_set_memtags (struct gdbarch *gdbarch, struct value *address,
|
||||
size_t length, const gdb::byte_vector &tags,
|
||||
enum memtag_type tag_type)
|
||||
{
|
||||
if (!value_valid_for_memtag (address))
|
||||
return 1;
|
||||
|
||||
/* Make sure we are dealing with a tagged address to begin with. */
|
||||
if (!aarch64_linux_tagged_address_p (gdbarch, address))
|
||||
return 1;
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
|
||||
/* Set the logical tag or the allocation tag. */
|
||||
if (tag_type == tag_logical)
|
||||
{
|
||||
/* When setting logical tags, we don't care about the length, since
|
||||
we are only setting a single logical tag. */
|
||||
addr = aarch64_linux_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 = value_contents_raw (address);
|
||||
store_unsigned_integer (srcbuf, sizeof (addr), byte_order, addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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 = get_tag_granules (addr, length, 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) != 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Implement the get_memtag gdbarch method. */
|
||||
|
||||
static struct value *
|
||||
aarch64_linux_get_memtag (struct gdbarch *gdbarch, struct value *address,
|
||||
enum memtag_type tag_type)
|
||||
{
|
||||
if (!value_valid_for_memtag (address))
|
||||
return nullptr;
|
||||
|
||||
/* Make sure we are dealing with a tagged address to begin with. */
|
||||
if (!aarch64_linux_tagged_address_p (gdbarch, address))
|
||||
return nullptr;
|
||||
|
||||
CORE_ADDR addr = value_as_address (address);
|
||||
CORE_ADDR tag = 0;
|
||||
|
||||
/* Get the logical tag or the allocation tag. */
|
||||
if (tag_type == tag_logical)
|
||||
tag = aarch64_linux_get_ltag (addr);
|
||||
else
|
||||
{
|
||||
if (aarch64_linux_get_atag (addr, &tag) != 0)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* 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 *address,
|
||||
enum memtag_type tag_type)
|
||||
{
|
||||
if (!value_valid_for_memtag (address))
|
||||
return "";
|
||||
|
||||
struct value *v_tag = aarch64_linux_get_memtag (gdbarch, address, tag_type);
|
||||
|
||||
if (v_tag == nullptr && tag_allocation)
|
||||
error (_("Error getting tag from target"));
|
||||
|
||||
CORE_ADDR tag = value_as_address (v_tag);
|
||||
|
||||
return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
|
||||
}
|
||||
|
||||
static void
|
||||
aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
{
|
||||
@@ -1514,6 +1755,31 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
data associated with the address. */
|
||||
set_gdbarch_significant_addr_bit (gdbarch, 56);
|
||||
|
||||
/* MTE-specific settings and hooks. */
|
||||
if (tdep->has_mte ())
|
||||
{
|
||||
/* 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 mismatch. */
|
||||
set_gdbarch_memtag_mismatch_p (gdbarch,
|
||||
aarch64_linux_memtag_mismatch_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, 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);
|
||||
}
|
||||
|
||||
/* Initialize the aarch64_linux_record_tdep. */
|
||||
/* These values are the size of the type that will be used in a system
|
||||
call. They are obtained from Linux Kernel source. */
|
||||
|
||||
@@ -78,6 +78,56 @@ legacy_register_sim_regno (struct gdbarch *gdbarch, int regnum)
|
||||
return LEGACY_SIM_REGNO_IGNORE;
|
||||
}
|
||||
|
||||
|
||||
/* See arch-utils.h */
|
||||
|
||||
std::string
|
||||
default_memtag_to_string (struct gdbarch *gdbarch, struct value *address,
|
||||
enum memtag_type tag_type)
|
||||
{
|
||||
/* By default, assume the address is untagged. */
|
||||
return "";
|
||||
}
|
||||
|
||||
/* See arch-utils.h */
|
||||
|
||||
bool
|
||||
default_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
|
||||
{
|
||||
/* By default, assume the address is untagged. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See arch-utils.h */
|
||||
|
||||
bool
|
||||
default_memtag_mismatch_p (struct gdbarch *gdbarch, struct value *address)
|
||||
{
|
||||
/* By default, assume there is no mismatch. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See arch-utils.h */
|
||||
|
||||
int
|
||||
default_set_memtags (struct gdbarch *gdbarch, struct value *address,
|
||||
size_t length, const gdb::byte_vector &tags,
|
||||
enum memtag_type tag_type)
|
||||
{
|
||||
/* By default, return 0; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See arch-utils.h */
|
||||
|
||||
struct value *
|
||||
default_get_memtag (struct gdbarch *gdbarch, struct value *address,
|
||||
enum memtag_type tag_type)
|
||||
{
|
||||
/* By default, return no tag. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
generic_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
|
||||
{
|
||||
|
||||
@@ -134,6 +134,29 @@ extern const struct floatformat **
|
||||
default_floatformat_for_type (struct gdbarch *gdbarch,
|
||||
const char *name, int len);
|
||||
|
||||
/* Default implementation of gdbarch_tagged_address_p. */
|
||||
extern std::string default_memtag_to_string (struct gdbarch *gdbarch,
|
||||
struct value *address,
|
||||
enum memtag_type tag_type);
|
||||
|
||||
/* Default implementation of gdbarch_tagged_address_p. */
|
||||
bool default_tagged_address_p (struct gdbarch *gdbarch, struct value *address);
|
||||
|
||||
/* Default implementation of gdbarch_memtag_mismatch_p. */
|
||||
extern bool default_memtag_mismatch_p (struct gdbarch *gdbarch,
|
||||
struct value *address);
|
||||
|
||||
/* Default implementation of gdbarch_set_memtags. */
|
||||
int default_set_memtags (struct gdbarch *gdbarch,
|
||||
struct value *address, size_t length,
|
||||
const gdb::byte_vector &tags,
|
||||
enum memtag_type tag_type);
|
||||
|
||||
/* Default implementation of gdbarch_get_memtag. */
|
||||
struct value *default_get_memtag (struct gdbarch *gdbarch,
|
||||
struct value *address,
|
||||
enum memtag_type tag_type);
|
||||
|
||||
extern CORE_ADDR generic_skip_trampoline_code (struct frame_info *frame,
|
||||
CORE_ADDR pc);
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
/* We have one tag per 16 bytes of memory. */
|
||||
#define MTE_GRANULE_SIZE 16
|
||||
#define MTE_LOGICAL_TAG_START_BIT 56
|
||||
#define MTE_LOGICAL_MAX_VALUE 0xf
|
||||
|
||||
/* Return the number of tag granules in the memory range
|
||||
[ADDR, ADDR + LEN) given GRANULE_SIZE. */
|
||||
|
||||
137
gdb/gdbarch.c
137
gdb/gdbarch.c
@@ -251,6 +251,12 @@ struct gdbarch
|
||||
gdbarch_convert_from_func_ptr_addr_ftype *convert_from_func_ptr_addr;
|
||||
gdbarch_addr_bits_remove_ftype *addr_bits_remove;
|
||||
int significant_addr_bit;
|
||||
gdbarch_memtag_to_string_ftype *memtag_to_string;
|
||||
gdbarch_tagged_address_p_ftype *tagged_address_p;
|
||||
gdbarch_memtag_mismatch_p_ftype *memtag_mismatch_p;
|
||||
gdbarch_set_memtags_ftype *set_memtags;
|
||||
gdbarch_get_memtag_ftype *get_memtag;
|
||||
CORE_ADDR memtag_granule_size;
|
||||
gdbarch_software_single_step_ftype *software_single_step;
|
||||
gdbarch_single_step_through_delay_ftype *single_step_through_delay;
|
||||
gdbarch_print_insn_ftype *print_insn;
|
||||
@@ -427,6 +433,11 @@ gdbarch_alloc (const struct gdbarch_info *info,
|
||||
gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr;
|
||||
gdbarch->convert_from_func_ptr_addr = convert_from_func_ptr_addr_identity;
|
||||
gdbarch->addr_bits_remove = core_addr_identity;
|
||||
gdbarch->memtag_to_string = default_memtag_to_string;
|
||||
gdbarch->tagged_address_p = default_tagged_address_p;
|
||||
gdbarch->memtag_mismatch_p = default_memtag_mismatch_p;
|
||||
gdbarch->set_memtags = default_set_memtags;
|
||||
gdbarch->get_memtag = default_get_memtag;
|
||||
gdbarch->print_insn = default_print_insn;
|
||||
gdbarch->skip_trampoline_code = generic_skip_trampoline_code;
|
||||
gdbarch->skip_solib_resolver = generic_skip_solib_resolver;
|
||||
@@ -616,6 +627,12 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
/* Skip verify of convert_from_func_ptr_addr, invalid_p == 0 */
|
||||
/* Skip verify of addr_bits_remove, invalid_p == 0 */
|
||||
/* Skip verify of significant_addr_bit, invalid_p == 0 */
|
||||
/* Skip verify of memtag_to_string, invalid_p == 0 */
|
||||
/* Skip verify of tagged_address_p, invalid_p == 0 */
|
||||
/* Skip verify of memtag_mismatch_p, invalid_p == 0 */
|
||||
/* Skip verify of set_memtags, invalid_p == 0 */
|
||||
/* Skip verify of get_memtag, invalid_p == 0 */
|
||||
/* Skip verify of memtag_granule_size, invalid_p == 0 */
|
||||
/* Skip verify of software_single_step, has predicate. */
|
||||
/* Skip verify of single_step_through_delay, has predicate. */
|
||||
/* Skip verify of print_insn, invalid_p == 0 */
|
||||
@@ -1055,6 +1072,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: get_longjmp_target = <%s>\n",
|
||||
host_address_to_string (gdbarch->get_longjmp_target));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: get_memtag = <%s>\n",
|
||||
host_address_to_string (gdbarch->get_memtag));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: get_pc_address_flags = <%s>\n",
|
||||
host_address_to_string (gdbarch->get_pc_address_flags));
|
||||
@@ -1190,6 +1210,15 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: memory_remove_breakpoint = <%s>\n",
|
||||
host_address_to_string (gdbarch->memory_remove_breakpoint));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: memtag_granule_size = %s\n",
|
||||
core_addr_to_string_nz (gdbarch->memtag_granule_size));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: memtag_mismatch_p = <%s>\n",
|
||||
host_address_to_string (gdbarch->memtag_mismatch_p));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: memtag_to_string = <%s>\n",
|
||||
host_address_to_string (gdbarch->memtag_to_string));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: num_pseudo_regs = %s\n",
|
||||
plongest (gdbarch->num_pseudo_regs));
|
||||
@@ -1334,6 +1363,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: sdb_reg_to_regnum = <%s>\n",
|
||||
host_address_to_string (gdbarch->sdb_reg_to_regnum));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: set_memtags = <%s>\n",
|
||||
host_address_to_string (gdbarch->set_memtags));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: short_bit = %s\n",
|
||||
plongest (gdbarch->short_bit));
|
||||
@@ -1448,6 +1480,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: syscalls_info = %s\n",
|
||||
host_address_to_string (gdbarch->syscalls_info));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: tagged_address_p = <%s>\n",
|
||||
host_address_to_string (gdbarch->tagged_address_p));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: target_desc = %s\n",
|
||||
host_address_to_string (gdbarch->target_desc));
|
||||
@@ -3220,6 +3255,108 @@ set_gdbarch_significant_addr_bit (struct gdbarch *gdbarch,
|
||||
gdbarch->significant_addr_bit = significant_addr_bit;
|
||||
}
|
||||
|
||||
std::string
|
||||
gdbarch_memtag_to_string (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->memtag_to_string != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_memtag_to_string called\n");
|
||||
return gdbarch->memtag_to_string (gdbarch, address, tag_type);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_memtag_to_string (struct gdbarch *gdbarch,
|
||||
gdbarch_memtag_to_string_ftype memtag_to_string)
|
||||
{
|
||||
gdbarch->memtag_to_string = memtag_to_string;
|
||||
}
|
||||
|
||||
bool
|
||||
gdbarch_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->tagged_address_p != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_tagged_address_p called\n");
|
||||
return gdbarch->tagged_address_p (gdbarch, address);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_tagged_address_p (struct gdbarch *gdbarch,
|
||||
gdbarch_tagged_address_p_ftype tagged_address_p)
|
||||
{
|
||||
gdbarch->tagged_address_p = tagged_address_p;
|
||||
}
|
||||
|
||||
bool
|
||||
gdbarch_memtag_mismatch_p (struct gdbarch *gdbarch, struct value *address)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->memtag_mismatch_p != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_memtag_mismatch_p called\n");
|
||||
return gdbarch->memtag_mismatch_p (gdbarch, address);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_memtag_mismatch_p (struct gdbarch *gdbarch,
|
||||
gdbarch_memtag_mismatch_p_ftype memtag_mismatch_p)
|
||||
{
|
||||
gdbarch->memtag_mismatch_p = memtag_mismatch_p;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_set_memtags (struct gdbarch *gdbarch, struct value *address, size_t length, const gdb::byte_vector &tags, enum memtag_type tag_type)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->set_memtags != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_set_memtags called\n");
|
||||
return gdbarch->set_memtags (gdbarch, address, length, tags, tag_type);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_set_memtags (struct gdbarch *gdbarch,
|
||||
gdbarch_set_memtags_ftype set_memtags)
|
||||
{
|
||||
gdbarch->set_memtags = set_memtags;
|
||||
}
|
||||
|
||||
struct value *
|
||||
gdbarch_get_memtag (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->get_memtag != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_get_memtag called\n");
|
||||
return gdbarch->get_memtag (gdbarch, address, tag_type);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_get_memtag (struct gdbarch *gdbarch,
|
||||
gdbarch_get_memtag_ftype get_memtag)
|
||||
{
|
||||
gdbarch->get_memtag = get_memtag;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
gdbarch_memtag_granule_size (struct gdbarch *gdbarch)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
/* Skip verify of memtag_granule_size, invalid_p == 0 */
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_memtag_granule_size called\n");
|
||||
return gdbarch->memtag_granule_size;
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_memtag_granule_size (struct gdbarch *gdbarch,
|
||||
CORE_ADDR memtag_granule_size)
|
||||
{
|
||||
gdbarch->memtag_granule_size = memtag_granule_size;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_software_single_step_p (struct gdbarch *gdbarch)
|
||||
{
|
||||
|
||||
@@ -115,6 +115,18 @@ enum function_call_return_method
|
||||
return_method_struct,
|
||||
};
|
||||
|
||||
enum memtag_type
|
||||
{
|
||||
/* Logical tag, the tag that is stored in unused bits of a pointer to a
|
||||
virtual address. */
|
||||
tag_logical = 0,
|
||||
|
||||
/* Allocation tag, the tag that is associated with every granule of memory in
|
||||
the physical address space. Allocation tags are used to validate memory
|
||||
accesses via pointers containing logical tags. */
|
||||
tag_allocation,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* The following are pre-initialized by GDBARCH. */
|
||||
@@ -705,6 +717,47 @@ extern void set_gdbarch_addr_bits_remove (struct gdbarch *gdbarch, gdbarch_addr_
|
||||
extern int gdbarch_significant_addr_bit (struct gdbarch *gdbarch);
|
||||
extern void set_gdbarch_significant_addr_bit (struct gdbarch *gdbarch, int significant_addr_bit);
|
||||
|
||||
/* Return a string representation of the memory tag TYPE of ADDRESS.
|
||||
If no tag is associated with such an address, return the empty string. */
|
||||
|
||||
typedef std::string (gdbarch_memtag_to_string_ftype) (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type);
|
||||
extern std::string gdbarch_memtag_to_string (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type);
|
||||
extern void set_gdbarch_memtag_to_string (struct gdbarch *gdbarch, gdbarch_memtag_to_string_ftype *memtag_to_string);
|
||||
|
||||
/* Return true if ADDRESS contains a tag and false otherwise. */
|
||||
|
||||
typedef bool (gdbarch_tagged_address_p_ftype) (struct gdbarch *gdbarch, struct value *address);
|
||||
extern bool gdbarch_tagged_address_p (struct gdbarch *gdbarch, struct value *address);
|
||||
extern void set_gdbarch_tagged_address_p (struct gdbarch *gdbarch, gdbarch_tagged_address_p_ftype *tagged_address_p);
|
||||
|
||||
/* Return true if the tag from ADDRESS does not match the memory tag for that
|
||||
particular address. Return false otherwise. */
|
||||
|
||||
typedef bool (gdbarch_memtag_mismatch_p_ftype) (struct gdbarch *gdbarch, struct value *address);
|
||||
extern bool gdbarch_memtag_mismatch_p (struct gdbarch *gdbarch, struct value *address);
|
||||
extern void set_gdbarch_memtag_mismatch_p (struct gdbarch *gdbarch, gdbarch_memtag_mismatch_p_ftype *memtag_mismatch_p);
|
||||
|
||||
/* Set the tags for the address range [ADDRESS, ADDRESS + LENGTH) to TAGS
|
||||
Return 0 if successful and non-zero otherwise. */
|
||||
|
||||
typedef int (gdbarch_set_memtags_ftype) (struct gdbarch *gdbarch, struct value *address, size_t length, const gdb::byte_vector &tags, enum memtag_type tag_type);
|
||||
extern int gdbarch_set_memtags (struct gdbarch *gdbarch, struct value *address, size_t length, const gdb::byte_vector &tags, enum memtag_type tag_type);
|
||||
extern void set_gdbarch_set_memtags (struct gdbarch *gdbarch, gdbarch_set_memtags_ftype *set_memtags);
|
||||
|
||||
/* Return the tag portion of ADDRESS, assuming ADDRESS is tagged. */
|
||||
|
||||
typedef struct value * (gdbarch_get_memtag_ftype) (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type);
|
||||
extern struct value * gdbarch_get_memtag (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type);
|
||||
extern void set_gdbarch_get_memtag (struct gdbarch *gdbarch, gdbarch_get_memtag_ftype *get_memtag);
|
||||
|
||||
/* memtag_granule_size is the size of the allocation tag granule, for
|
||||
architectures that support memory tagging.
|
||||
This is 0 for architectures that do not support memory tagging.
|
||||
For a non-zero value, this represents the number of bytes of memory per tag. */
|
||||
|
||||
extern CORE_ADDR gdbarch_memtag_granule_size (struct gdbarch *gdbarch);
|
||||
extern void set_gdbarch_memtag_granule_size (struct gdbarch *gdbarch, CORE_ADDR memtag_granule_size);
|
||||
|
||||
/* FIXME/cagney/2001-01-18: This should be split in two. A target method that
|
||||
indicates if the target needs software single step. An ISA method to
|
||||
implement it.
|
||||
|
||||
@@ -604,6 +604,30 @@ m;CORE_ADDR;addr_bits_remove;CORE_ADDR addr;addr;;core_addr_identity;;0
|
||||
# additional data associated with the address.
|
||||
v;int;significant_addr_bit;;;;;;0
|
||||
|
||||
# Return a string representation of the memory tag TYPE of ADDRESS.
|
||||
# If no tag is associated with such an address, return the empty string.
|
||||
+m;std::string;memtag_to_string;struct value *address, enum memtag_type tag_type;address, tag_type;;default_memtag_to_string;;0
|
||||
|
||||
# Return true if ADDRESS contains a tag and false otherwise.
|
||||
+m;bool;tagged_address_p;struct value *address;address;;default_tagged_address_p;;0
|
||||
|
||||
# Return true if the tag from ADDRESS does not match the memory tag for that
|
||||
# particular address. Return false otherwise.
|
||||
+m;bool;memtag_mismatch_p;struct value *address;address;;default_memtag_mismatch_p;;0
|
||||
|
||||
# Set the tags for the address range [ADDRESS, ADDRESS + LENGTH) to TAGS
|
||||
# Return 0 if successful and non-zero otherwise.
|
||||
+m;int;set_memtags;struct value *address, size_t length, const gdb::byte_vector \&tags, enum memtag_type tag_type;address, length, tags, tag_type;;default_set_memtags;;0
|
||||
|
||||
# Return the tag portion of ADDRESS, assuming ADDRESS is tagged.
|
||||
+m;struct value *;get_memtag;struct value *address, enum memtag_type tag_type;address, tag_type;;default_get_memtag;;0
|
||||
|
||||
# memtag_granule_size is the size of the allocation tag granule, for
|
||||
# architectures that support memory tagging.
|
||||
# This is 0 for architectures that do not support memory tagging.
|
||||
# For a non-zero value, this represents the number of bytes of memory per tag.
|
||||
v;CORE_ADDR;memtag_granule_size;;;;;;0
|
||||
|
||||
# FIXME/cagney/2001-01-18: This should be split in two. A target method that
|
||||
# indicates if the target needs software single step. An ISA method to
|
||||
# implement it.
|
||||
@@ -1355,6 +1379,18 @@ enum function_call_return_method
|
||||
return_method_struct,
|
||||
};
|
||||
|
||||
enum memtag_type
|
||||
{
|
||||
/* Logical tag, the tag that is stored in unused bits of a pointer to a
|
||||
virtual address. */
|
||||
tag_logical = 0,
|
||||
|
||||
/* Allocation tag, the tag that is associated with every granule of memory in
|
||||
the physical address space. Allocation tags are used to validate memory
|
||||
accesses via pointers containing logical tags. */
|
||||
tag_allocation,
|
||||
};
|
||||
|
||||
EOF
|
||||
|
||||
# function typedef's
|
||||
|
||||
Reference in New Issue
Block a user