@@ -1728,7 +1728,7 @@ pass_in_v (struct gdbarch *gdbarch,
{
int regnum = AARCH64_V0_REGNUM + info->nsrn;
/* Enough space for a full vector register. */
- gdb::byte_vector reg (register_size (gdbarch, regnum), 0);
+ gdb::byte_vector reg (regcache->register_size (regnum), 0);
gdb_assert (len <= reg.size ());
info->argnum++;
@@ -2543,7 +2543,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
{
int regno = AARCH64_V0_REGNUM + i;
/* Enough space for a full vector register. */
- gdb::byte_vector buf (register_size (gdbarch, regno));
+ gdb::byte_vector buf (regs->register_size (regno));
gdb_assert (len <= buf.size ());
aarch64_debug_printf
@@ -2657,7 +2657,7 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
{
int regno = AARCH64_V0_REGNUM + i;
/* Enough space for a full vector register. */
- gdb::byte_vector tmpbuf (register_size (gdbarch, regno));
+ gdb::byte_vector tmpbuf (regs->register_size (regno));
gdb_assert (len <= tmpbuf.size ());
aarch64_debug_printf
@@ -3308,7 +3308,8 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, const frame_info_ptr &next_frame,
various 'scalar' pseudo registers to behavior like architectural
writes, register width bytes are written the remainder are set to
zero. */
- gdb::byte_vector raw_buf (register_size (gdbarch, raw_regnum), 0);
+ int raw_reg_size = register_size (gdbarch, raw_regnum, &next_frame);
+ gdb::byte_vector raw_buf (raw_reg_size, 0);
static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
gdb::array_view<gdb_byte> raw_view (raw_buf);
@@ -1151,13 +1151,14 @@ eval_op_register (struct type *expect_type, struct expression *exp,
if (regno == -1)
error (_("Register $%s not available."), name);
- /* In EVAL_AVOID_SIDE_EFFECTS mode, we only need to return
- a value with the appropriate register type. Unfortunately,
- we don't have easy access to the type of user registers.
- So for these registers, we fetch the register value regardless
- of the evaluation mode. */
+ /* In EVAL_AVOID_SIDE_EFFECTS mode, we only need to return a value with
+ the appropriate register type. Unfortunately, we don't have easy
+ access to the type of user registers and variable-size registers. So
+ for these registers, we fetch the register value regardless of the
+ evaluation mode. */
if (noside == EVAL_AVOID_SIDE_EFFECTS
- && regno < gdbarch_num_cooked_regs (exp->gdbarch))
+ && regno < gdbarch_num_cooked_regs (exp->gdbarch)
+ && !register_is_variable_size (exp->gdbarch, regno))
val = value::zero (register_type (exp->gdbarch, regno), not_lval);
else
val = value_of_register
@@ -562,11 +562,12 @@ read_frame_register_value (value *value)
LONGEST reg_offset = value->offset ();
int regnum = value->regnum ();
int len = type_length_units (check_typedef (value->type ()));
+ int reg_size = register_size (gdbarch, regnum, &next_frame);
/* Skip registers wholly inside of REG_OFFSET. */
- while (reg_offset >= register_size (gdbarch, regnum))
+ while (reg_offset >= reg_size)
{
- reg_offset -= register_size (gdbarch, regnum);
+ reg_offset -= reg_size;
regnum++;
}
@@ -1322,12 +1322,24 @@ frame_unwind_register_value (const frame_info_ptr &next_frame, int regnum)
gdb_printf (&debug_file, " lazy");
else if (value->entirely_available ())
{
- int i;
+ int i, reg_size;
gdb::array_view<const gdb_byte> buf = value->contents ();
gdb_printf (&debug_file, " bytes=");
gdb_printf (&debug_file, "[");
- for (i = 0; i < register_size (gdbarch, regnum); i++)
+
+ if (register_is_variable_size (gdbarch, regnum))
+ /* To get the size of a variable-size register, we need to
+ call frame_save_as_regcache () so that we can call
+ regcache::register_size (). Unfortunatlly the former
+ ends up calling this function so we enter into an
+ infinite recursion. So just assume that the value has
+ the correct size. */
+ reg_size = buf.size ();
+ else
+ reg_size = register_size (gdbarch, regnum);
+
+ for (i = 0; i < reg_size; i++)
gdb_printf (&debug_file, "%02x", buf[i]);
gdb_printf (&debug_file, "]");
}
@@ -1446,7 +1458,7 @@ put_frame_register (const frame_info_ptr &next_frame, int regnum,
int unavail;
enum lval_type lval;
CORE_ADDR addr;
- int size = register_size (gdbarch, regnum);
+ int size = register_size (gdbarch, regnum, &next_frame);
gdb_assert (buf.size () == size);
@@ -1462,8 +1474,9 @@ put_frame_register (const frame_info_ptr &next_frame, int regnum,
break;
}
case lval_register:
- /* Not sure if that's always true... but we have a problem if not. */
- gdb_assert (size == register_size (gdbarch, realnum));
+ if (regnum != realnum)
+ /* Not sure if that's always true... but we have a problem if not. */
+ gdb_assert (size == register_size (gdbarch, realnum));
if (realnum < gdbarch_num_regs (gdbarch)
|| !gdbarch_pseudo_register_write_p (gdbarch))
@@ -1509,9 +1522,9 @@ get_frame_register_bytes (const frame_info_ptr &next_frame, int regnum,
gdbarch *gdbarch = frame_unwind_arch (next_frame);
/* Skip registers wholly inside of OFFSET. */
- while (offset >= register_size (gdbarch, regnum))
+ while (offset >= register_size (gdbarch, regnum, &next_frame))
{
- offset -= register_size (gdbarch, regnum);
+ offset -= register_size (gdbarch, regnum, &next_frame);
regnum++;
}
@@ -1521,7 +1534,7 @@ get_frame_register_bytes (const frame_info_ptr &next_frame, int regnum,
int numregs = gdbarch_num_cooked_regs (gdbarch);
for (int i = regnum; i < numregs; i++)
{
- int thissize = register_size (gdbarch, i);
+ int thissize = register_size (gdbarch, i, &next_frame);
if (thissize == 0)
break; /* This register is not available on this architecture. */
@@ -1535,10 +1548,10 @@ get_frame_register_bytes (const frame_info_ptr &next_frame, int regnum,
/* Copy the data. */
while (!buffer.empty ())
{
- int curr_len = std::min<int> (register_size (gdbarch, regnum) - offset,
- buffer.size ());
+ int reg_size = register_size (gdbarch, regnum, &next_frame);
+ int curr_len = std::min<int> (reg_size - offset, buffer.size ());
- if (curr_len == register_size (gdbarch, regnum))
+ if (curr_len == reg_size)
{
enum lval_type lval;
CORE_ADDR addr;
@@ -1586,19 +1599,19 @@ put_frame_register_bytes (const frame_info_ptr &next_frame, int regnum,
gdbarch *gdbarch = frame_unwind_arch (next_frame);
/* Skip registers wholly inside of OFFSET. */
- while (offset >= register_size (gdbarch, regnum))
+ while (offset >= register_size (gdbarch, regnum, &next_frame))
{
- offset -= register_size (gdbarch, regnum);
+ offset -= register_size (gdbarch, regnum, &next_frame);
regnum++;
}
/* Copy the data. */
while (!buffer.empty ())
{
- int curr_len = std::min<int> (register_size (gdbarch, regnum) - offset,
- buffer.size ());
+ int reg_size = register_size (gdbarch, regnum, &next_frame);
+ int curr_len = std::min<int> (reg_size - offset, buffer.size ());
- if (curr_len == register_size (gdbarch, regnum))
+ if (curr_len == reg_size)
put_frame_register (next_frame, regnum, buffer.slice (0, curr_len));
else
{
@@ -399,12 +399,11 @@ static inline struct record_full_entry *
record_full_reg_alloc (struct regcache *regcache, int regnum)
{
struct record_full_entry *rec;
- struct gdbarch *gdbarch = regcache->arch ();
rec = XCNEW (struct record_full_entry);
rec->type = record_full_reg;
rec->u.reg.num = regnum;
- rec->u.reg.len = register_size (gdbarch, regnum);
+ rec->u.reg.len = regcache->register_size (regnum);
if (rec->u.reg.len > sizeof (rec->u.reg.u.buf))
rec->u.reg.u.ptr = (gdb_byte *) xmalloc (rec->u.reg.len);
@@ -51,7 +51,7 @@ struct regcache_descr
redundant information - if the PC is constructed from two
registers then those registers and not the PC lives in the raw
cache. */
- long sizeof_raw_registers = 0;
+ long sizeof_fixed_size_raw_registers = 0;
/* The cooked register space. Each cooked register in the range
[0..NR_RAW_REGISTERS) is direct-mapped onto the corresponding raw
@@ -60,7 +60,7 @@ struct regcache_descr
both raw registers and memory by the architecture methods
gdbarch_pseudo_register_read and gdbarch_pseudo_register_write. */
int nr_cooked_registers = 0;
- long sizeof_cooked_registers = 0;
+ long sizeof_fixed_size_cooked_registers = 0;
/* Offset and size (in 8 bit bytes), of each register in the
register cache. All registers (including those in the range
@@ -69,9 +69,16 @@ struct regcache_descr
long *register_offset = nullptr;
long *sizeof_register = nullptr;
- /* Registers that need to be loaded early in the register cache. */
+ /* Registers that need to be loaded early in the register cache, because
+ variable-size registers depend on them to calculate their size. */
std::set<int> load_early_regs;
+ /* Vector indicating whether a given register is variable-size. */
+ bool *register_is_variable_size = nullptr;
+
+ /* Does the regcache contains any variable-size register? */
+ bool has_variable_size_registers = false;
+
/* Cached table containing the type of each register. */
struct type **register_type = nullptr;
};
@@ -119,26 +126,52 @@ init_regcache_descr (struct gdbarch *gdbarch)
= GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long);
descr->register_offset
= GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long);
+ descr->register_is_variable_size
+ = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, bool);
+
for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
{
- descr->sizeof_register[i] = descr->register_type[i]->length ();
- descr->register_offset[i] = offset;
- offset += descr->sizeof_register[i];
+ descr->register_is_variable_size[i]
+ = is_dynamic_type (descr->register_type[i]);
+ if (descr->register_is_variable_size[i])
+ {
+ descr->sizeof_register[i] = -1;
+ descr->register_offset[i] = -1;
+ descr->has_variable_size_registers = true;
+ }
+ else
+ {
+ descr->sizeof_register[i] = descr->register_type[i]->length ();
+ descr->register_offset[i] = offset;
+ offset += descr->sizeof_register[i];
+ }
if (tdesc_register_is_early_load (gdbarch, i))
descr->load_early_regs.insert (i);
}
+
/* Set the real size of the raw register cache buffer. */
- descr->sizeof_raw_registers = offset;
+ descr->sizeof_fixed_size_raw_registers = offset;
for (; i < descr->nr_cooked_registers; i++)
{
- descr->sizeof_register[i] = descr->register_type[i]->length ();
- descr->register_offset[i] = offset;
- offset += descr->sizeof_register[i];
+ descr->register_is_variable_size[i]
+ = is_dynamic_type (descr->register_type[i]);
+ if (descr->register_is_variable_size[i])
+ {
+ descr->sizeof_register[i] = -1;
+ descr->register_offset[i] = -1;
+ descr->has_variable_size_registers = true;
+ }
+ else
+ {
+ descr->sizeof_register[i] = descr->register_type[i]->length ();
+ descr->register_offset[i] = offset;
+ offset += descr->sizeof_register[i];
+ }
}
/* Set the real size of the readonly register cache buffer. */
- descr->sizeof_cooked_registers = offset;
+ descr->sizeof_fixed_size_cooked_registers = offset;
}
return descr;
@@ -160,27 +193,60 @@ regcache_descr (struct gdbarch *gdbarch)
/* Utility functions returning useful register attributes stored in
the regcache descr. */
+/* See gdb/regcache.h. */
+
struct type *
register_type (struct gdbarch *gdbarch, int regnum)
{
struct regcache_descr *descr = regcache_descr (gdbarch);
gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers);
- return descr->register_type[regnum];
+
+ struct type *type = descr->register_type[regnum];
+
+ if (descr->register_is_variable_size[regnum])
+ {
+ frame_info_ptr current_frame = get_current_frame ();
+ type = resolve_dynamic_type (type, {}, 0, ¤t_frame);
+ }
+
+ return type;
}
-/* Utility functions returning useful register attributes stored in
- the regcache descr. */
+/* See gdb/regcache.h. */
int
-register_size (struct gdbarch *gdbarch, int regnum)
+register_size (struct gdbarch *gdbarch, int regnum,
+ const frame_info_ptr *next_frame)
{
struct regcache_descr *descr = regcache_descr (gdbarch);
- int size;
- gdb_assert (regnum >= 0 && regnum < gdbarch_num_cooked_regs (gdbarch));
- size = descr->sizeof_register[regnum];
- return size;
+ gdb_assert (regnum >= 0);
+ gdb_assert (regnum < descr->nr_cooked_registers);
+
+ if (descr->register_is_variable_size[regnum])
+ {
+ gdb_assert (next_frame != nullptr);
+
+ std::unique_ptr<readonly_detached_regcache> regcache =
+ frame_save_as_regcache (get_prev_frame (*next_frame));
+ return regcache->register_size (regnum);
+ }
+
+ return descr->sizeof_register[regnum];
+}
+
+/* See gdb/regcache.h. */
+
+bool
+register_is_variable_size (struct gdbarch *gdbarch, int regnum)
+{
+ struct regcache_descr *descr = regcache_descr (gdbarch);
+
+ gdb_assert (regnum >= 0);
+ gdb_assert (regnum < descr->nr_cooked_registers);
+
+ return descr->register_is_variable_size[regnum];
}
/* See gdbsupport/common-regcache.h. */
@@ -188,7 +254,47 @@ register_size (struct gdbarch *gdbarch, int regnum)
int
reg_buffer::register_size (int regnum) const
{
- return ::register_size (this->arch (), regnum);
+ gdb_assert (regnum >= 0);
+ gdb_assert (regnum < m_descr->nr_cooked_registers);
+
+ int size;
+
+ if (m_descr->register_is_variable_size[regnum])
+ {
+ if (!m_variable_size_registers)
+ const_cast<reg_buffer *> (this)
+ ->initialize_variable_size_registers (); // FIXME: Remove cast.
+
+ size = m_variable_size_register_sizeof[regnum];
+ }
+ else
+ size = m_descr->sizeof_register[regnum];
+
+ return size;
+}
+
+/* See gdb/regcache.h. */
+
+struct type *
+reg_buffer::register_type (int regnum) const
+{
+ gdb_assert (regnum >= 0);
+ gdb_assert (regnum < m_descr->nr_cooked_registers);
+
+ struct type *type;
+
+ if (m_descr->register_is_variable_size[regnum])
+ {
+ if (!m_variable_size_registers)
+ const_cast<reg_buffer *> (this)
+ ->initialize_variable_size_registers (); // FIXME: Remove cast.
+
+ type = m_variable_size_register_type[regnum];
+ }
+ else
+ type = m_descr->register_type[regnum];
+
+ return type;
}
reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo)
@@ -202,13 +308,13 @@ reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo)
REG_VALID. */
if (has_pseudo)
{
- m_registers.reset (new gdb_byte[m_descr->sizeof_cooked_registers]);
+ m_fixed_size_registers.reset (new gdb_byte[m_descr->sizeof_fixed_size_cooked_registers]);
m_register_status.reset
(new register_status[m_descr->nr_cooked_registers] ());
}
else
{
- m_registers.reset (new gdb_byte[m_descr->sizeof_raw_registers]);
+ m_fixed_size_registers.reset (new gdb_byte[m_descr->sizeof_fixed_size_raw_registers]);
m_register_status.reset
(new register_status[gdbarch_num_regs (gdbarch)] ());
}
@@ -237,9 +343,6 @@ reg_buffer::arch () const
return m_descr->gdbarch;
}
-/* Utility functions returning useful register attributes stored in
- the regcache descr. */
-
/* See regcache.h. */
bool
@@ -281,6 +384,55 @@ reg_buffer::load_early_registers ()
return m_descr->load_early_regs;
}
+/* See regcache.h. */
+
+void
+reg_buffer::initialize_variable_size_registers ()
+{
+ unsigned long total_size = 0;
+
+ /* We need load early registers to resolve types of variable-size
+ registers. */
+ if (!this->fetch_load_early_registers ())
+ error (_("Missing register contents for variable-size registers."));
+
+ m_variable_size_register_type.resize (m_descr->nr_cooked_registers);
+ m_variable_size_register_sizeof.resize (m_descr->nr_cooked_registers);
+ m_variable_size_register_offset.resize (m_descr->nr_cooked_registers);
+
+ for (unsigned int i = 0; i < m_descr->nr_cooked_registers; i++)
+ {
+ if (!m_descr->register_is_variable_size[i])
+ {
+ m_variable_size_register_type[i] = nullptr;
+ m_variable_size_register_sizeof[i] = -1;
+ m_variable_size_register_offset[i] = -1;
+ continue;
+ }
+
+ m_variable_size_register_type[i]
+ = resolve_dynamic_type (m_descr->register_type[i], {},
+ /* Unused address. */ 0, nullptr, this);
+
+ ULONGEST size = m_variable_size_register_type[i]->length ();
+ gdb_assert (size != 0);
+ m_variable_size_register_sizeof[i] = size;
+ m_variable_size_register_offset[i] = total_size;
+ m_register_status[i] = REG_UNKNOWN;
+ total_size += size;
+ }
+
+ m_variable_size_registers.reset (new gdb_byte[total_size]);
+}
+
+/* See regcache.h. */
+
+bool
+reg_buffer::has_variable_size_registers ()
+{
+ return m_descr->has_variable_size_registers;
+}
+
/* Helper for reg_buffer::register_buffer. */
template<typename ElemType>
@@ -288,8 +440,19 @@ gdb::array_view<ElemType>
reg_buffer::register_buffer (int regnum) const
{
assert_regnum (regnum);
- ElemType *start = &m_registers[m_descr->register_offset[regnum]];
- int size = m_descr->sizeof_register[regnum];
+ ElemType *start;
+
+ if (m_descr->register_is_variable_size[regnum])
+ {
+ if (!m_variable_size_registers)
+ const_cast<reg_buffer *>(this)->initialize_variable_size_registers (); // FIXME: Remove cast.
+
+ start = &m_variable_size_registers[m_variable_size_register_offset[regnum]];
+ }
+ else
+ start = &m_fixed_size_registers[m_descr->register_offset[regnum]];
+
+ int size = register_size (regnum);
return gdb::array_view<ElemType> (start, size);
}
@@ -317,9 +480,14 @@ reg_buffer::save (register_read_ftype cooked_read)
/* It should have pseudo registers. */
gdb_assert (m_has_pseudo);
/* Clear the dest. */
- memset (m_registers.get (), 0, m_descr->sizeof_cooked_registers);
+ memset (m_fixed_size_registers.get (), 0, m_descr->sizeof_fixed_size_cooked_registers);
memset (m_register_status.get (), REG_UNKNOWN, m_descr->nr_cooked_registers);
+ /* For data related to variable-size registers, we only need to reset
+ their buffer at this point. Other data will be resized/re-set by
+ initialize_variable_size_registers (). */
+ m_variable_size_registers.reset ();
+
/* Save load early registers first. */
for (int regnum : m_descr->load_early_regs)
{
@@ -379,6 +547,12 @@ regcache::restore (readonly_detached_regcache *src)
continue;
cooked_write (regnum, src->register_buffer (regnum));
+
+ if (m_variable_size_registers)
+ /* For data related to variable-size registers, we only need to reset
+ their buffer at this point. Other data will be resized/re-set by
+ initialize_variable_size_registers (). */
+ m_variable_size_registers.reset ();
}
/* Copy over any registers, being careful to only restore those that
@@ -709,7 +883,7 @@ register_status
readable_regcache::raw_read (int regnum, gdb::array_view<gdb_byte> dst)
{
assert_regnum (regnum);
- gdb_assert (dst.size () == m_descr->sizeof_register[regnum]);
+ gdb_assert (dst.size () == register_size (regnum));
raw_update (regnum);
@@ -725,7 +899,7 @@ register_status
readable_regcache::raw_read (int regnum, gdb_byte *dst)
{
assert_regnum (regnum);
- int size = m_descr->sizeof_register[regnum];
+ int size = register_size (regnum);
return raw_read (regnum, gdb::make_array_view (dst, size));
}
@@ -741,7 +915,7 @@ enum register_status
readable_regcache::raw_read (int regnum, T *val)
{
assert_regnum (regnum);
- size_t size = m_descr->sizeof_register[regnum];
+ size_t size = register_size (regnum);
gdb_byte *buf = (gdb_byte *) alloca (size);
auto view = gdb::make_array_view (buf, size);
register_status status = raw_read (regnum, view);
@@ -776,7 +950,7 @@ regcache::raw_write (int regnum, T val)
{
assert_regnum (regnum);
- int size = m_descr->sizeof_register[regnum];
+ int size = register_size (regnum);
gdb_byte *buf = (gdb_byte *) alloca (size);
auto view = gdb::make_array_view (buf, size);
store_integer (view, gdbarch_byte_order (m_descr->gdbarch), val);
@@ -815,7 +989,7 @@ readable_regcache::cooked_read (int regnum, gdb::array_view<gdb_byte> dst)
if (regnum < num_raw_registers ())
return raw_read (regnum, dst);
- gdb_assert (dst.size () == m_descr->sizeof_register[regnum]);
+ gdb_assert (dst.size () == register_size (regnum));
if (m_has_pseudo && m_register_status[regnum] != REG_UNKNOWN)
{
@@ -857,7 +1031,7 @@ readable_regcache::cooked_read (int regnum, gdb_byte *dst)
gdb_assert (regnum >= 0);
gdb_assert (regnum < m_descr->nr_cooked_registers);
- int size = m_descr->sizeof_register[regnum];
+ int size = register_size (regnum);
return cooked_read (regnum, gdb::make_array_view (dst, size));
}
@@ -871,8 +1045,12 @@ readable_regcache::cooked_read_value (int regnum)
|| (m_has_pseudo && m_register_status[regnum] != REG_UNKNOWN)
|| !gdbarch_pseudo_register_read_value_p (m_descr->gdbarch))
{
+ /* Provide the register type if its size is fixed to avoid infinite
+ recursion in the case of variable-size registers. */
+ struct type *type = (m_descr->register_is_variable_size[regnum] ?
+ nullptr : m_descr->register_type[regnum]);
value *result = value::allocate_register
- (get_next_frame_sentinel_okay (get_current_frame ()), regnum);
+ (get_next_frame_sentinel_okay (get_current_frame ()), regnum, type);
/* It is more efficient in general to do this delegation in this
direction than in the other one, even though the value-based
@@ -902,7 +1080,7 @@ enum register_status
readable_regcache::cooked_read (int regnum, T *val)
{
gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
- size_t size = m_descr->sizeof_register[regnum];
+ size_t size = register_size (regnum);
gdb_byte *buf = (gdb_byte *) alloca (size);
auto view = gdb::make_array_view (buf, size);
register_status status = cooked_read (regnum, view);
@@ -936,7 +1114,7 @@ regcache::cooked_write (int regnum, T val)
gdb_assert (regnum >= 0);
gdb_assert (regnum < m_descr->nr_cooked_registers);
- int size = m_descr->sizeof_register[regnum];
+ int size = register_size (regnum);
gdb_byte *buf = (gdb_byte *) alloca (size);
auto view = gdb::make_array_view (buf, size);
store_integer (view, gdbarch_byte_order (m_descr->gdbarch), val);
@@ -955,7 +1133,7 @@ void
regcache::raw_write (int regnum, gdb::array_view<const gdb_byte> src)
{
assert_regnum (regnum);
- gdb_assert (src.size () == m_descr->sizeof_register[regnum]);
+ gdb_assert (src.size () == register_size (regnum));
/* On the sparc, writing %g0 is a no-op, so we don't even want to
change the registers array if something writes to this register. */
@@ -992,7 +1170,7 @@ regcache::raw_write (int regnum, const gdb_byte *src)
{
assert_regnum (regnum);
- int size = m_descr->sizeof_register[regnum];
+ int size = register_size (regnum);
raw_write (regnum, gdb::make_array_view (src, size));
}
@@ -1023,7 +1201,7 @@ regcache::cooked_write (int regnum, const gdb_byte *src)
gdb_assert (regnum >= 0);
gdb_assert (regnum < m_descr->nr_cooked_registers);
- int size = m_descr->sizeof_register[regnum];
+ int size = register_size (regnum);
return cooked_write (regnum, gdb::make_array_view (src, size));
}
@@ -1235,6 +1413,11 @@ reg_buffer::raw_supply (int regnum, gdb::array_view<const gdb_byte> src)
{
copy (src, dst);
m_register_status[regnum] = REG_VALID;
+
+ if (this->is_load_early_register (regnum)
+ && memcmp (src.data (), dst.data (), dst.size ()))
+ /* Invalidate variable-size registers. */
+ this->initialize_variable_size_registers ();
}
else
{
@@ -1253,7 +1436,7 @@ reg_buffer::raw_supply (int regnum, const void *src)
{
assert_regnum (regnum);
- int size = m_descr->sizeof_register[regnum];
+ int size = register_size (regnum);
raw_supply (regnum, gdb::make_array_view ((const gdb_byte *) src, size));
}
@@ -1297,7 +1480,7 @@ reg_buffer::raw_collect (int regnum, void *dst) const
{
assert_regnum (regnum);
- int size = m_descr->sizeof_register[regnum];
+ int size = register_size (regnum);
return raw_collect (regnum, gdb::make_array_view ((gdb_byte *) dst, size));
}
@@ -1372,7 +1555,7 @@ regcache::transfer_regset (const struct regset *regset, int regbase,
regno += regbase;
if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
- slot_size = m_descr->sizeof_register[regno];
+ slot_size = register_size (regnum);
if (regno == REGCACHE_MAP_SKIP
|| (regnum != -1
@@ -165,10 +165,15 @@ extern bool regcache_map_supplies (const struct regcache_map_entry *map,
extern struct type *register_type (struct gdbarch *gdbarch, int regnum);
-/* Return the size of register REGNUM. All registers should have only
- one size. */
+/* Return the size of register REGNUM. FRAME is needed in case regnum is a
+ variable-size register. */
-extern int register_size (struct gdbarch *gdbarch, int regnum);
+extern int register_size (struct gdbarch *gdbarch, int regnum,
+ const frame_info_ptr *next_frame = nullptr);
+
+/* Return whether REGNUM is a variable-size register. */
+
+extern bool register_is_variable_size (struct gdbarch *gdbarch, int regnum);
using register_read_ftype
= gdb::function_view<register_status (int, gdb::array_view<gdb_byte>)>;
@@ -266,6 +271,12 @@ class reg_buffer : public reg_buffer_common
/* Return set of regnums which need to be loaded before other registers. */
const std::set<int> &load_early_registers ();
+ /* Whether any register in this regcache has a dynamic type. */
+ bool has_variable_size_registers ();
+
+ /* Return type of register REGNUM. */
+ struct type *register_type (int regnum) const;
+
/* See gdbsupport/common-regcache.h. */
int register_size (int regnum) const override;
@@ -279,6 +290,10 @@ class reg_buffer : public reg_buffer_common
Return false if they aren't. */
virtual bool fetch_load_early_registers ();
+ /* Initialize (or reset) information about variable-size registers in this
+ reg_buffer. */
+ void initialize_variable_size_registers ();
+
/* Return a view on register REGNUM's buffer cache. */
template <typename ElemType>
gdb::array_view<ElemType> register_buffer (int regnum) const;
@@ -293,11 +308,25 @@ class reg_buffer : public reg_buffer_common
struct regcache_descr *m_descr;
bool m_has_pseudo;
- /* The register buffers. */
- std::unique_ptr<gdb_byte[]> m_registers;
+
+ /* The fixed-size register buffers. */
+ std::unique_ptr<gdb_byte[]> m_fixed_size_registers;
+
+ /* The variable-size register buffers (if any). */
+ std::unique_ptr<gdb_byte[]> m_variable_size_registers;
+
/* Register cache status. */
std::unique_ptr<register_status[]> m_register_status;
+ /* The resolved types for variable-size registers (if any). */
+ std::vector<struct type *> m_variable_size_register_type;
+
+ /* The size of resolved types for variable-size registers (if any). */
+ std::vector<long> m_variable_size_register_sizeof;
+
+ /* The offset of resolved types for variable-size registers (if any). */
+ std::vector<long> m_variable_size_register_offset;
+
friend class regcache;
friend class detached_regcache;
};
@@ -471,6 +471,8 @@ struct packet_reg
at present. */
};
+struct remote_state;
+
struct remote_arch_state
{
explicit remote_arch_state (struct gdbarch *gdbarch);
@@ -493,6 +495,10 @@ struct remote_arch_state
/* This is the maximum size (in chars) of a non read/write packet.
It is also used as a cap on the size of read/write packets. */
long remote_packet_size;
+
+ /* Make sure the maximum packet size reflects current size of variable-size
+ registers. */
+ void update_packet_size (const struct regcache *regcache, remote_state *rs);
};
/* Description of the remote protocol state for the currently
@@ -1897,7 +1903,8 @@ show_remote_exec_file (struct ui_file *file, int from_tty,
}
static int
-map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs)
+map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs,
+ const struct regcache *regcache = nullptr)
{
int regnum, num_remote_regs, offset;
struct packet_reg **remote_regs;
@@ -1905,8 +1912,15 @@ map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs)
for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++)
{
struct packet_reg *r = ®s[regnum];
+ bool skip_register;
- if (register_size (gdbarch, regnum) == 0)
+ if (regcache == nullptr)
+ skip_register = (register_is_variable_size (gdbarch, regnum)
+ || register_size (gdbarch, regnum) == 0);
+ else
+ skip_register = regcache->register_size (regnum) == 0;
+
+ if (skip_register)
/* Do not try to fetch zero-sized (placeholder) registers. */
r->pnum = -1;
else
@@ -1934,7 +1948,10 @@ map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs)
{
remote_regs[regnum]->in_g_packet = 1;
remote_regs[regnum]->offset = offset;
- offset += register_size (gdbarch, remote_regs[regnum]->regnum);
+ if (regcache == nullptr)
+ offset += register_size (gdbarch, remote_regs[regnum]->regnum);
+ else
+ offset += regcache->register_size (remote_regs[regnum]->regnum);
}
return offset;
@@ -1995,6 +2012,29 @@ remote_arch_state::remote_arch_state (struct gdbarch *gdbarch)
this->remote_packet_size = (this->sizeof_g_packet * 2 + 32);
}
+/* See remote_arch_state class declaration. */
+
+void
+remote_arch_state::update_packet_size (const struct regcache *regcache,
+ remote_state *rs)
+{
+ /* Record the maximum possible size of the g packet - it may turn out
+ to be smaller. */
+ this->sizeof_g_packet
+ = map_regcache_remote_table (regcache->arch (), this->regs.get (),
+ regcache);
+
+ this->remote_packet_size = 400 - 1;
+
+ if (this->sizeof_g_packet > (this->remote_packet_size - 32) / 2)
+ this->remote_packet_size = this->sizeof_g_packet * 2 + 32;
+
+ /* Make sure that the packet buffer is plenty big enough for
+ this architecture. */
+ if (rs->buf.size () < this->remote_packet_size)
+ rs->buf.resize (2 * this->remote_packet_size);
+}
+
/* Get a pointer to the current remote target. If not connected to a
remote target, return NULL. */
@@ -8553,6 +8593,10 @@ remote_target::supply_expedited_regs (struct regcache *regcache,
regcache->raw_supply (reg.num, reg.data);
rs->last_seen_expedited_registers.insert (reg.num);
}
+
+ if (regcache->has_variable_size_registers ())
+ get_remote_state ()->get_remote_arch_state (regcache->arch ())
+ ->update_packet_size (regcache, &m_remote_state);
}
/* Called when it is decided that STOP_REPLY holds the info of the
@@ -8979,6 +9023,9 @@ remote_target::fetch_early_registers (struct regcache *regcache)
if (res == 0)
error (_("Could not load early register %d using p packet."), regnum);
}
+
+ get_remote_state ()->get_remote_arch_state (regcache->arch ())
+ ->update_packet_size (regcache, &m_remote_state);
}
/* Fetch the registers included in the target's 'g' packet. */
@@ -9054,7 +9101,7 @@ remote_target::process_g_packet (struct regcache *regcache)
for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
{
long offset = rsa->regs[i].offset;
- long reg_size = register_size (gdbarch, i);
+ long reg_size = regcache->register_size (i);
if (rsa->regs[i].pnum == -1)
continue;
@@ -9102,7 +9149,7 @@ remote_target::process_g_packet (struct regcache *regcache)
for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
{
struct packet_reg *r = &rsa->regs[i];
- long reg_size = register_size (gdbarch, i);
+ long reg_size = regcache->register_size (i);
if (r->in_g_packet)
{
@@ -9240,7 +9287,8 @@ remote_target::store_register_using_P (const struct regcache *regcache,
struct remote_state *rs = get_remote_state ();
/* Try storing a single register. */
char *buf = rs->buf.data ();
- gdb_byte *regp = (gdb_byte *) alloca (register_size (gdbarch, reg->regnum));
+ int reg_size = regcache->register_size (reg->regnum);
+ gdb_byte *regp = (gdb_byte *) alloca (reg_size);
char *p;
if (m_features.packet_support (PACKET_P) == PACKET_DISABLE)
@@ -9252,7 +9300,7 @@ remote_target::store_register_using_P (const struct regcache *regcache,
xsnprintf (buf, get_remote_packet_size (), "P%s=", phex_nz (reg->pnum, 0));
p = buf + strlen (buf);
regcache->raw_collect (reg->regnum, regp);
- bin2hex (regp, p, register_size (gdbarch, reg->regnum));
+ bin2hex (regp, p, reg_size);
putpkt (rs->buf);
getpkt (&rs->buf);
@@ -4071,12 +4071,24 @@ value::fetch_lazy_register ()
if (new_val->entirely_available ())
{
- int i;
+ int i, reg_size;
gdb::array_view<const gdb_byte> buf = new_val->contents ();
gdb_printf (&debug_file, " bytes=");
gdb_printf (&debug_file, "[");
- for (i = 0; i < register_size (gdbarch, regnum); i++)
+
+ if (register_is_variable_size (gdbarch, regnum))
+ /* To get the size of a variable-size register, we need to
+ call frame_save_as_regcache () so that we can call
+ regcache::register_size (). Unfortunatlly the former
+ ends up calling this function so we enter into an
+ infinite recursion. So just assume that the value has
+ the correct size. */
+ reg_size = buf.size ();
+ else
+ reg_size = register_size (gdbarch, regnum);
+
+ for (i = 0; i < reg_size; i++)
gdb_printf (&debug_file, "%02x", buf[i]);
gdb_printf (&debug_file, "]");
}
@@ -115,7 +115,9 @@ struct tdesc_reg : tdesc_element
/* The target-described type corresponding to TYPE, if found. */
struct tdesc_type *tdesc_type;
- /* Whether this register needs to be loaded early in GDB's regcache.
+ /* Whether this register needs to be loaded early in GDB's regcache,
+ because it is used to evaluate the DWARF expression giving the size of
+ another register.
In addition, if true gdbserver will send it as an expedited register
in stop replies. */