From d734c63af73c6d774013e0091683246381b5ce63 Mon Sep 17 00:00:00 2001 From: Lancelot SIX Date: Mon, 19 Sep 2022 12:30:12 +0100 Subject: [PATCH] gdb/poke: Support the $reg::REGNAME syntax Make it possible to use $reg::REGNAME to access the content of a register from poke expressions. --- gdb/doc/poke.texi | 42 ++++++++++++++++++++++++++++++++++++++ gdb/poke.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/gdb/doc/poke.texi b/gdb/doc/poke.texi index c7a3a8b43a4..8af56a224b8 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 e2833ed6bba..9bb24236d2f 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 } @@ -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; -- 2.47.2