diff options
author | Yao Qi <yao.qi@linaro.org> | 2018-02-21 11:20:03 +0000 |
---|---|---|
committer | Yao Qi <yao.qi@linaro.org> | 2018-02-21 11:20:03 +0000 |
commit | 215c69dc9a7d8f868198b5523abcf41458fb6e4a (patch) | |
tree | cb0eec51f7b956a8f3d46d37986504b1ca059c95 | |
parent | f3384e664de76c4bb9f8fd9920afcec86557f1f0 (diff) | |
download | gdb-215c69dc9a7d8f868198b5523abcf41458fb6e4a.zip gdb-215c69dc9a7d8f868198b5523abcf41458fb6e4a.tar.gz gdb-215c69dc9a7d8f868198b5523abcf41458fb6e4a.tar.bz2 |
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.
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/infcmd.c | 6 | ||||
-rw-r--r-- | gdb/regcache.c | 71 | ||||
-rw-r--r-- | gdb/regcache.h | 10 |
4 files changed, 67 insertions, 29 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 64b4cd2..30db821 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 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. (register_dump_regcache, register_dump_none): New class. (register_dump_remote, register_dump_groups): New class. diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 331fd87..c10a498 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -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: diff --git a/gdb/regcache.c b/gdb/regcache.c index 389c016..8f81163 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -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. */ diff --git a/gdb/regcache.h b/gdb/regcache.h index a377d2d..6531aff 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -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. */ |