return cap[0] != 0;
}
+/* AArch64 Linux implementation of the set_cap_tag_from_address gdbarch
+ hook. Sets the tag from the capability located at ADDR to TAG. */
+
+static void
+aarch64_linux_set_cap_tag_from_address (struct gdbarch *gdbarch, CORE_ADDR addr,
+ bool tag)
+{
+ gdb::byte_vector cap;
+
+ /* Read original capability at ADDR. */
+ cap = target_read_capability (addr);
+
+ cap[0] = tag? 1 : 0;
+
+ /* Write back the same contents but with a custom tag. */
+ target_write_capability (addr, cap);
+}
+
/* Return the number of Morello memory tag granules contained in the memory
range [addr, addr + len). */
aarch64_linux_report_signal_info);
set_gdbarch_get_cap_tag_from_address (gdbarch,
aarch64_linux_get_cap_tag_from_address);
+ set_gdbarch_set_cap_tag_from_address (gdbarch,
+ aarch64_linux_set_cap_tag_from_address);
/* Core file helpers. */
std::vector<stack_item_t> si;
};
-/* Helper function to set a TAG for a particular register REGNUM. */
+/* Implementation of the gdbarch_register_set_tag hook. */
static void
-set_register_tag (struct gdbarch *gdbarch, struct regcache *regcache,
- int regnum, bool tag)
+aarch64_register_set_tag (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, bool tag)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* We need to read the tags from memory. */
gdb::byte_vector cap = target_read_capability (address);
bool tag = cap[0] == 0 ? false : true;
- set_register_tag (gdbarch, regcache, regnum, tag);
+ aarch64_register_set_tag (gdbarch, regcache, regnum, tag);
if (aarch64_debug)
debug_printf ("aarch64: %s Read tag %s from address %s\n",
capability. */
struct value *clr = regcache->cooked_read_value (regnum);
regcache->cooked_write (regnum, value_contents (clr));
- set_register_tag (gdbarch, regcache, regnum, value_tag (clr));
+ aarch64_register_set_tag (gdbarch, regcache, regnum, value_tag (clr));
}
if (aarch64_debug)
capability. */
struct value *csp = regcache->cooked_read_value (regnum);
regcache->cooked_write (regnum, value_contents (csp));
- set_register_tag (gdbarch, regcache, regnum, value_tag (csp));
+ aarch64_register_set_tag (gdbarch, regcache, regnum, value_tag (csp));
}
if (aarch64_debug)
struct value *csp = regcache->cooked_read_value (regnum);
regcache->cooked_write (regnum, value_contents (csp));
- set_register_tag (gdbarch, regcache, regnum, value_tag (csp));
+ aarch64_register_set_tag (gdbarch, regcache, regnum, value_tag (csp));
}
if (aarch64_debug)
/* Also store the tag if we are dealing with a capability. */
if (aapcs64_cap || type->code () == TYPE_CODE_CAPABILITY)
- set_register_tag (gdbarch, regs, regno, value_tag (value));
+ aarch64_register_set_tag (gdbarch, regs, regno, value_tag (value));
}
else if (type->code () == TYPE_CODE_INT
|| type->code () == TYPE_CODE_CHAR
/* We need to read the tags from memory. */
gdb::byte_vector cap = target_read_capability (address);
bool tag = cap[0] == 0 ? false : true;
- set_register_tag (gdbarch, regs, regno, tag);
+ aarch64_register_set_tag (gdbarch, regs, regno, tag);
if (aarch64_debug)
debug_printf ("aarch64: %s Read tag %s from address %s\n",
regcache->raw_write_part (c_real_regnum, 0, 8, lower_bytes);
regcache->raw_write_part (c_real_regnum, 8, 8, upper_bytes);
- set_register_tag (gdbarch, regcache, c_real_regnum,
- (tag != 0)? true : false);
+ aarch64_register_set_tag (gdbarch, regcache, c_real_regnum,
+ (tag != 0)? true : false);
return;
}
/* For fetching register tag information. */
set_gdbarch_register_has_tag (gdbarch, aarch64_register_has_tag);
set_gdbarch_register_tag (gdbarch, aarch64_register_tag);
+ set_gdbarch_register_set_tag (gdbarch, aarch64_register_set_tag);
/* Create the Morello register aliases. */
/* cip0 and cip1 */
return false;
}
+/* See arch-utils.h. */
+void
+default_register_set_tag (struct gdbarch *gdbarch,
+ regcache *regcache,
+ int cookednum, bool tag)
+{
+ return;
+}
+
/* See arch-utils.h. */
bool default_get_cap_tag_from_address (struct gdbarch *gdbarch,
CORE_ADDR addr)
return false;
}
+/* See arch-utils.h. */
+void
+default_set_cap_tag_from_address (struct gdbarch *gdbarch,
+ CORE_ADDR addr, bool tag)
+{
+ return;
+}
+
void _initialize_gdbarch_utils ();
void
_initialize_gdbarch_utils ()
readable_regcache *regcache,
int cookednum);
+/* Default implementation of gdbarch_register_set_tag. */
+extern void default_register_set_tag (struct gdbarch *gdbarch,
+ regcache *regcache,
+ int cookednum, bool tag);
+
/* Default implementation of gdbarch_cap_tag_from_address. */
extern bool default_get_cap_tag_from_address (struct gdbarch *gdbarch,
CORE_ADDR addr);
+
+/* Default implementation of gdbarch_set_cap_tag_from_address. */
+extern void default_set_cap_tag_from_address (struct gdbarch *gdbarch,
+ CORE_ADDR addr, bool tag);
#endif /* ARCH_UTILS_H */
return false;
}
+void
+put_frame_register (struct frame_info *frame, int regnum,
+ const gdb_byte *buf, struct value *fromval)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ int realnum;
+ int optim;
+ int unavail;
+ enum lval_type lval;
+ CORE_ADDR addr;
+
+ frame_register (frame, regnum, &optim, &unavail,
+ &lval, &addr, &realnum, NULL);
+ if (optim)
+ error (_("Attempt to assign to a register that was not saved."));
+
+ struct type *val_type = value_type (fromval);
+
+ switch (lval)
+ {
+ case lval_memory:
+ {
+ write_memory (addr, buf, register_size (gdbarch, regnum));
+
+ /* If this value is a capability, we need to handle the capability tag
+ as well. */
+ if ((val_type->code () == TYPE_CODE_CAPABILITY
+ || (val_type->code () == TYPE_CODE_PTR
+ && TYPE_CAPABILITY (val_type)))
+ && value_tagged (fromval))
+ gdbarch_set_cap_tag_from_address (gdbarch, addr, value_tag (fromval));
+ break;
+ }
+ case lval_register:
+ {
+ get_current_regcache ()->cooked_write (realnum, buf);
+ /* If this value is a capability, we need to handle the capability tag
+ as well. */
+ if ((val_type->code () == TYPE_CODE_CAPABILITY
+ || (val_type->code () == TYPE_CODE_PTR
+ && TYPE_CAPABILITY (val_type)))
+ && value_tagged (fromval))
+ {
+ gdbarch_register_set_tag (gdbarch, get_current_regcache (),
+ regnum, value_tag (fromval));
+ }
+ }
+ break;
+ default:
+ error (_("Attempt to assign to an unmodifiable value."));
+ }
+}
+
void
put_frame_register (struct frame_info *frame, int regnum,
const gdb_byte *buf)
return true;
}
+void
+put_frame_register_value (struct frame_info *frame, int regnum,
+ CORE_ADDR offset, struct value *fromval)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ int len = TYPE_LENGTH (value_type (fromval));
+ const gdb_byte *myaddr = value_contents (fromval);
+
+ /* Skip registers wholly inside of OFFSET. */
+ while (offset >= register_size (gdbarch, regnum))
+ {
+ offset -= register_size (gdbarch, regnum);
+ regnum++;
+ }
+
+ /* Copy the data. */
+ while (len > 0)
+ {
+ int curr_len = register_size (gdbarch, regnum) - offset;
+
+ if (curr_len > len)
+ curr_len = len;
+
+ if (curr_len == register_size (gdbarch, regnum))
+ {
+ put_frame_register (frame, regnum, myaddr, fromval);
+ }
+ else
+ {
+ struct value *value = frame_unwind_register_value (frame->next,
+ regnum);
+ gdb_assert (value != NULL);
+
+ memcpy ((char *) value_contents_writeable (value) + offset, myaddr,
+ curr_len);
+ put_frame_register (frame, regnum, value_contents_raw (value),
+ fromval);
+ release_value (value);
+ }
+
+ myaddr += curr_len;
+ len -= curr_len;
+ offset = 0;
+ regnum++;
+ }
+}
+
void
put_frame_register_bytes (struct frame_info *frame, int regnum,
CORE_ADDR offset, int len, const gdb_byte *myaddr)
extern void put_frame_register (struct frame_info *frame, int regnum,
const gdb_byte *buf);
+/* Same as put_frame_register, but passing a struct value *. */
+extern void put_frame_register (struct frame_info *frame, int regnum,
+ const gdb_byte *buf, struct value *fromval);
+
/* Read LEN bytes from one or multiple registers starting with REGNUM
in frame FRAME, starting at OFFSET, into BUF. If the register
contents are optimized out or unavailable, set *OPTIMIZEDP,
CORE_ADDR offset, int len,
const gdb_byte *myaddr);
+/* Same as put_frame_register_bytes, but passing a struct value *. */
+extern void put_frame_register_value (struct frame_info *frame, int regnum,
+ CORE_ADDR offset, struct value *fromval);
+
/* Unwind the PC. Strictly speaking return the resume address of the
calling frame. For GDB, `pc' is the resume address and not a
specific register. */
CORE_ADDR deprecated_function_start_offset;
gdbarch_remote_register_number_ftype *remote_register_number;
gdbarch_get_cap_tag_from_address_ftype *get_cap_tag_from_address;
+ gdbarch_set_cap_tag_from_address_ftype *set_cap_tag_from_address;
gdbarch_fetch_tls_load_module_address_ftype *fetch_tls_load_module_address;
gdbarch_get_thread_local_address_ftype *get_thread_local_address;
CORE_ADDR frame_args_skip;
gdbarch_read_core_file_mappings_ftype *read_core_file_mappings;
gdbarch_register_has_tag_ftype *register_has_tag;
gdbarch_register_tag_ftype *register_tag;
+ gdbarch_register_set_tag_ftype *register_set_tag;
};
/* Create a new ``struct gdbarch'' based on information provided by
gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint;
gdbarch->remote_register_number = default_remote_register_number;
gdbarch->get_cap_tag_from_address = default_get_cap_tag_from_address;
+ gdbarch->set_cap_tag_from_address = default_set_cap_tag_from_address;
gdbarch->unwind_pc = default_unwind_pc;
gdbarch->unwind_sp = default_unwind_sp;
gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr;
gdbarch->read_core_file_mappings = default_read_core_file_mappings;
gdbarch->register_has_tag = default_register_has_tag;
gdbarch->register_tag = default_register_tag;
+ gdbarch->register_set_tag = default_register_set_tag;
/* gdbarch_alloc() */
return gdbarch;
/* Skip verify of deprecated_function_start_offset, invalid_p == 0 */
/* Skip verify of remote_register_number, invalid_p == 0 */
/* Skip verify of get_cap_tag_from_address, invalid_p == 0 */
+ /* Skip verify of set_cap_tag_from_address, invalid_p == 0 */
/* Skip verify of fetch_tls_load_module_address, has predicate. */
/* Skip verify of get_thread_local_address, has predicate. */
/* Skip verify of frame_args_skip, invalid_p == 0 */
/* Skip verify of read_core_file_mappings, invalid_p == 0 */
/* Skip verify of register_has_tag, invalid_p == 0 */
/* Skip verify of register_tag, invalid_p == 0 */
+ /* Skip verify of register_set_tag, invalid_p == 0 */
if (!log.empty ())
internal_error (__FILE__, __LINE__,
_("verify_gdbarch: the following are invalid ...%s"),
fprintf_unfiltered (file,
"gdbarch_dump: register_reggroup_p = <%s>\n",
host_address_to_string (gdbarch->register_reggroup_p));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: register_set_tag = <%s>\n",
+ host_address_to_string (gdbarch->register_set_tag));
fprintf_unfiltered (file,
"gdbarch_dump: register_sim_regno = <%s>\n",
host_address_to_string (gdbarch->register_sim_regno));
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_cap_tag_from_address = <%s>\n",
+ host_address_to_string (gdbarch->set_cap_tag_from_address));
fprintf_unfiltered (file,
"gdbarch_dump: short_bit = %s\n",
plongest (gdbarch->short_bit));
gdbarch->get_cap_tag_from_address = get_cap_tag_from_address;
}
+void
+gdbarch_set_cap_tag_from_address (struct gdbarch *gdbarch, CORE_ADDR addr, bool tag)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->set_cap_tag_from_address != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_set_cap_tag_from_address called\n");
+ gdbarch->set_cap_tag_from_address (gdbarch, addr, tag);
+}
+
+void
+set_gdbarch_set_cap_tag_from_address (struct gdbarch *gdbarch,
+ gdbarch_set_cap_tag_from_address_ftype set_cap_tag_from_address)
+{
+ gdbarch->set_cap_tag_from_address = set_cap_tag_from_address;
+}
+
int
gdbarch_fetch_tls_load_module_address_p (struct gdbarch *gdbarch)
{
gdbarch->register_tag = register_tag;
}
+void
+gdbarch_register_set_tag (struct gdbarch *gdbarch, regcache *regcache, int cookednum, bool tag)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->register_set_tag != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_register_set_tag called\n");
+ gdbarch->register_set_tag (gdbarch, regcache, cookednum, tag);
+}
+
+void
+set_gdbarch_register_set_tag (struct gdbarch *gdbarch,
+ gdbarch_register_set_tag_ftype register_set_tag)
+{
+ gdbarch->register_set_tag = register_set_tag;
+}
+
/* Keep a registry of per-architecture data-pointers required by GDB
modules. */
extern bool gdbarch_get_cap_tag_from_address (struct gdbarch *gdbarch, CORE_ADDR addr);
extern void set_gdbarch_get_cap_tag_from_address (struct gdbarch *gdbarch, gdbarch_get_cap_tag_from_address_ftype *get_cap_tag_from_address);
+/* Set the tag from a capability stored at address ADDR to TAG. */
+
+typedef void (gdbarch_set_cap_tag_from_address_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr, bool tag);
+extern void gdbarch_set_cap_tag_from_address (struct gdbarch *gdbarch, CORE_ADDR addr, bool tag);
+extern void set_gdbarch_set_cap_tag_from_address (struct gdbarch *gdbarch, gdbarch_set_cap_tag_from_address_ftype *set_cap_tag_from_address);
+
/* Fetch the target specific address used to represent a load module. */
extern int gdbarch_fetch_tls_load_module_address_p (struct gdbarch *gdbarch);
extern bool gdbarch_register_tag (struct gdbarch *gdbarch, readable_regcache *regcache, int cookednum);
extern void set_gdbarch_register_tag (struct gdbarch *gdbarch, gdbarch_register_tag_ftype *register_tag);
+/* Sets the register tag to TAG. */
+
+typedef void (gdbarch_register_set_tag_ftype) (struct gdbarch *gdbarch, regcache *regcache, int cookednum, bool tag);
+extern void gdbarch_register_set_tag (struct gdbarch *gdbarch, regcache *regcache, int cookednum, bool tag);
+extern void set_gdbarch_register_set_tag (struct gdbarch *gdbarch, gdbarch_register_set_tag_ftype *register_set_tag);
+
extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
# Return the tag from a capability stored at address ADDR.
m;bool;get_cap_tag_from_address;CORE_ADDR addr;addr;0;default_get_cap_tag_from_address;;0
+# Set the tag from a capability stored at address ADDR to TAG.
+m;void;set_cap_tag_from_address;CORE_ADDR addr, bool tag;addr, tag;0;default_set_cap_tag_from_address;;0
+
# Fetch the target specific address used to represent a load module.
F;CORE_ADDR;fetch_tls_load_module_address;struct objfile *objfile;objfile
# Returns true if the register tag bit is 1 and false otherwise.
# The default is to always return false.
m;bool;register_tag;readable_regcache *regcache, int cookednum;regcache, cookednum;;default_register_tag;;0
+# Sets the register tag to TAG.
+m;void;register_set_tag;regcache *regcache, int cookednum, bool tag;regcache, cookednum, tag;;default_register_set_tag;;0
EOF
}
return;
store_registers_using_G (regcache);
+ fetch_registers_using_g (regcache);
return;
}
}
else
{
- put_frame_register_bytes (frame, value_reg,
+ put_frame_register_value (frame, value_reg,
value_offset (toval),
- TYPE_LENGTH (type),
- value_contents (fromval));
+ fromval);
}
}