No longer create readonly regcache
Nowadays, we create a readonly regcache in get_return_value, and pass it to gdbarch_return_value to get the return value. In theory, we can pass a readable_regcache instance and get the return value, because we don't need to modify the regcache. Unfortunately, gdbarch_return_value is designed to multiplex regcache, according to READBUF and WRITEBUF. # If READBUF is not NULL, extract the return value and save it in this # buffer. # # If WRITEBUF is not NULL, it contains a return value which will be # stored into the appropriate register. In fact, gdbarch_return_value should be split to three functions, 1) only return return_value_convention, 2) pass regcache_readonly and readbuf, 3) pass regcache and writebuf. These changes are out of the scope of this patch series, so I pass regcache to gdbarch_return_value even for read, and trust each gdbarch backend doesn't modify regcache. gdb: 2018-02-21 Yao Qi <yao.qi@linaro.org> * infcmd.c (get_return_value): Let stop_regs point to get_current_regcache. * regcache.c (regcache::regcache): Remove. (register_dump_reg_buffer): New class. (regcache_print): Adjust. * regcache.h (regcache): Remove constructors.
This commit is contained in:
parent
f3384e664d
commit
215c69dc9a
@ -1,3 +1,12 @@
|
||||
2018-02-21 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* infcmd.c (get_return_value): Let stop_regs point to
|
||||
get_current_regcache.
|
||||
* regcache.c (regcache::regcache): Remove.
|
||||
(register_dump_reg_buffer): New class.
|
||||
(regcache_print): Adjust.
|
||||
* regcache.h (regcache): Remove constructors.
|
||||
|
||||
2018-02-21 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* regcache.c (class register_dump): New class.
|
||||
|
@ -1625,8 +1625,8 @@ advance_command (const char *arg, int from_tty)
|
||||
struct value *
|
||||
get_return_value (struct value *function, struct type *value_type)
|
||||
{
|
||||
regcache stop_regs (regcache::readonly, *get_current_regcache ());
|
||||
struct gdbarch *gdbarch = stop_regs.arch ();
|
||||
regcache *stop_regs = get_current_regcache ();
|
||||
struct gdbarch *gdbarch = stop_regs->arch ();
|
||||
struct value *value;
|
||||
|
||||
value_type = check_typedef (value_type);
|
||||
@ -1646,7 +1646,7 @@ get_return_value (struct value *function, struct type *value_type)
|
||||
case RETURN_VALUE_ABI_RETURNS_ADDRESS:
|
||||
case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
|
||||
value = allocate_value (value_type);
|
||||
gdbarch_return_value (gdbarch, function, value_type, &stop_regs,
|
||||
gdbarch_return_value (gdbarch, function, value_type, stop_regs,
|
||||
value_contents_raw (value), NULL);
|
||||
break;
|
||||
case RETURN_VALUE_STRUCT_CONVENTION:
|
||||
|
@ -219,13 +219,6 @@ do_cooked_read (void *src, int regnum, gdb_byte *buf)
|
||||
return regcache_cooked_read (regcache, regnum, buf);
|
||||
}
|
||||
|
||||
regcache::regcache (readonly_t, const regcache &src)
|
||||
: regcache (src.arch (), nullptr, true)
|
||||
{
|
||||
gdb_assert (!src.m_readonly_p);
|
||||
save (do_cooked_read, (void *) &src);
|
||||
}
|
||||
|
||||
readonly_detached_regcache::readonly_detached_regcache (const regcache &src)
|
||||
: readonly_detached_regcache (src.arch (), do_cooked_read, (void *) &src)
|
||||
{
|
||||
@ -1512,6 +1505,55 @@ private:
|
||||
const bool m_dump_pseudo;
|
||||
};
|
||||
|
||||
/* Dump from reg_buffer, used when there is no thread or
|
||||
registers. */
|
||||
|
||||
class register_dump_reg_buffer : public register_dump, reg_buffer
|
||||
{
|
||||
public:
|
||||
register_dump_reg_buffer (gdbarch *gdbarch, bool dump_pseudo)
|
||||
: register_dump (gdbarch), reg_buffer (gdbarch, dump_pseudo)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void dump_reg (ui_file *file, int regnum) override
|
||||
{
|
||||
if (regnum < 0)
|
||||
{
|
||||
if (m_has_pseudo)
|
||||
fprintf_unfiltered (file, "Cooked value");
|
||||
else
|
||||
fprintf_unfiltered (file, "Raw value");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
|
||||
{
|
||||
auto size = register_size (m_gdbarch, regnum);
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
auto status = get_register_status (regnum);
|
||||
|
||||
gdb_assert (status != REG_VALID);
|
||||
|
||||
if (status == REG_UNKNOWN)
|
||||
fprintf_unfiltered (file, "<invalid>");
|
||||
else
|
||||
fprintf_unfiltered (file, "<unavailable>");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just print "<cooked>" for pseudo register when
|
||||
regcache_dump_raw. */
|
||||
fprintf_unfiltered (file, "<cooked>");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* For "maint print registers". */
|
||||
|
||||
class register_dump_none : public register_dump
|
||||
@ -1633,22 +1675,19 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
|
||||
case regcache_dump_raw:
|
||||
case regcache_dump_cooked:
|
||||
{
|
||||
regcache *reg;
|
||||
auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
|
||||
|
||||
if (target_has_registers)
|
||||
reg = get_current_regcache ();
|
||||
dump.reset (new register_dump_regcache (get_current_regcache (),
|
||||
dump_pseudo));
|
||||
else
|
||||
{
|
||||
/* For the benefit of "maint print registers" & co when
|
||||
debugging an executable, allow dumping a regcache even when
|
||||
there is no thread selected / no registers. */
|
||||
reg = new regcache (target_gdbarch ());
|
||||
regs.reset (reg);
|
||||
dump.reset (new register_dump_reg_buffer (target_gdbarch (),
|
||||
dump_pseudo));
|
||||
}
|
||||
|
||||
auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
|
||||
|
||||
dump.reset (new register_dump_regcache (reg, dump_pseudo));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1937,7 +1976,7 @@ cooked_read_test (struct gdbarch *gdbarch)
|
||||
mock_target.reset ();
|
||||
}
|
||||
|
||||
regcache readonly (regcache::readonly, readwrite);
|
||||
readonly_detached_regcache readonly (readwrite);
|
||||
|
||||
/* GDB may go to target layer to fetch all registers and memory for
|
||||
readonly regcache. */
|
||||
|
@ -307,16 +307,6 @@ class readonly_detached_regcache;
|
||||
class regcache : public detached_regcache
|
||||
{
|
||||
public:
|
||||
regcache (gdbarch *gdbarch)
|
||||
: regcache (gdbarch, nullptr, true)
|
||||
{}
|
||||
|
||||
struct readonly_t {};
|
||||
static constexpr readonly_t readonly {};
|
||||
|
||||
/* Create a readonly regcache from a non-readonly regcache. */
|
||||
regcache (readonly_t, const regcache &src);
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (regcache);
|
||||
|
||||
/* Return REGCACHE's address space. */
|
||||
|
Loading…
Reference in New Issue
Block a user