aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLancelot SIX <lsix@lancelotsix.com>2022-09-19 12:30:12 +0100
committerLancelot SIX <lancelot.six@amd.com>2022-09-24 21:41:33 +0100
commitd734c63af73c6d774013e0091683246381b5ce63 (patch)
treea37e70036e40686f469747241557707ca580d5a6
parent21c2659b8edc2cd70bfe291272bb5ea080a95b9a (diff)
downloadfsf-binutils-gdb-d734c63af73c6d774013e0091683246381b5ce63.zip
fsf-binutils-gdb-d734c63af73c6d774013e0091683246381b5ce63.tar.gz
fsf-binutils-gdb-d734c63af73c6d774013e0091683246381b5ce63.tar.bz2
gdb/poke: Support the $reg::REGNAME syntax
Make it possible to use $reg::REGNAME to access the content of a register from poke expressions.
-rw-r--r--gdb/doc/poke.texi42
-rw-r--r--gdb/poke.c52
2 files changed, 94 insertions, 0 deletions
diff --git a/gdb/doc/poke.texi b/gdb/doc/poke.texi
index c7a3a8b..8af56a2 100644
--- a/gdb/doc/poke.texi
+++ b/gdb/doc/poke.texi
@@ -373,3 +373,45 @@ struct_person @{
postal_address=0x5555555547c5UL#B
@}
@end smallexample
+
+Poke can read registers in the target by using the @code{$reg::REGNAME}
+notation. The read is done in the context of the selected frame.
+
+The following example shows how poke could be used to decode the value of the
+@code{EFLAGS} register of the x86 ISA:
+
+@smallexample
+(@value{GDBN}) poke type EFlags_T =
+ struct uint<32>
+ @{
+ uint<27> other_flags;
+ uint<1> AF;
+ uint<1> r2 = 0;
+ uint<1> PF;
+ uint<1> r1 = 1;
+ uint<1> CF;
+ @}
+(@value{GDBN}) poke $reg::eflags as EFlags_T
+EFlags_T @{
+ other_flags=(uint<27>) 0x12,
+ AF=(uint<1>) 0x0,
+ r2=(uint<1>) 0x0,
+ PF=(uint<1>) 0x1,
+ r1=(uint<1>) 0x1,
+ CF=(uint<1>) 0x0
+@}
+@end smallexample
+
+It can also be useful to interpret the content of a register as an address. To
+do so, it is possible to use the @code{$reg::REGNAME#B} notation.
+
+For example, the following can be used to inspect the current stack frame:
+
+@smallexample
+(@value{GDBN}) poke load "std-types.pk"
+(@value{GDBN}) poke load ios
+(@value{GDBN}) poke ios_dump_bytes :ios get_ios :from $reg::sp#B
+ :size ($reg::fp - $reg::sp)#B
+ :group_by 1#B
+00007fffffffddd0: 0d f0 ad de 00 00 00 00 ef be ad de 00 00 00 00
+@end smallexample
diff --git a/gdb/poke.c b/gdb/poke.c
index e2833ed..9bb2423 100644
--- a/gdb/poke.c
+++ b/gdb/poke.c
@@ -22,6 +22,7 @@
#include "arch-utils.h"
#include "target.h"
#include "gdbcmd.h"
+#include "user-regs.h"
extern "C" {
#include <libpoke.h>
}
@@ -320,6 +321,57 @@ poke_alien_token_handler (const char *id, char **errmsg)
= (gdbarch_addressable_memory_unit_size (target_gdbarch ())
* 8);
}
+ else if (strncmp (id, "reg::", 5) == 0)
+ {
+ const std::string regname { id + 5 };
+
+ if (!target_has_registers ())
+ {
+ *errmsg
+ = xstrdup (string_printf (_("cannot read register '%s': "
+ "target has no registers"),
+ regname.c_str ()).c_str ());
+ return nullptr;
+ }
+
+ frame_info *frame = get_selected_frame ();
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ const int regnum
+ = user_reg_map_name_to_regnum (gdbarch, regname.c_str (),
+ regname.length ());
+
+ if (regnum == -1)
+ {
+ *errmsg = xstrdup (string_printf (_("unknown register '%s'"),
+ regname.c_str ()).c_str ());
+ return nullptr;
+ }
+
+ struct value *reg_value;
+
+ try
+ {
+ reg_value = value_of_register (regnum, frame);
+ }
+ catch (const gdb_exception_error &except)
+ {
+ *errmsg
+ = xstrdup (string_printf (_("failed to fetch register '%s' "
+ "for selected frame"),
+ regname.c_str ()).c_str ());
+ return nullptr;
+ }
+
+ struct type *type = value_type (reg_value);
+
+ alien_token.kind = PK_ALIEN_TOKEN_INTEGER;
+ alien_token.value.integer.magnitude
+ = value_as_long (reg_value);
+ alien_token.value.integer.width
+ = TYPE_LENGTH (type) * HOST_CHAR_BIT;
+ alien_token.value.integer.signed_p
+ = !type->is_unsigned ();
+ }
else
{
struct value *value;