diff options
author | Lancelot SIX <lsix@lancelotsix.com> | 2022-09-19 12:30:12 +0100 |
---|---|---|
committer | Lancelot SIX <lancelot.six@amd.com> | 2022-09-24 21:41:33 +0100 |
commit | d734c63af73c6d774013e0091683246381b5ce63 (patch) | |
tree | a37e70036e40686f469747241557707ca580d5a6 | |
parent | 21c2659b8edc2cd70bfe291272bb5ea080a95b9a (diff) | |
download | binutils-d734c63af73c6d774013e0091683246381b5ce63.zip binutils-d734c63af73c6d774013e0091683246381b5ce63.tar.gz binutils-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.texi | 42 | ||||
-rw-r--r-- | gdb/poke.c | 52 |
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 @@ -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; |