]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/poke: Support the $reg::REGNAME syntax
authorLancelot SIX <lsix@lancelotsix.com>
Mon, 19 Sep 2022 11:30:12 +0000 (12:30 +0100)
committerLancelot SIX <lancelot.six@amd.com>
Sat, 24 Sep 2022 20:41:33 +0000 (21:41 +0100)
Make it possible to use $reg::REGNAME to access the content of a
register from poke expressions.

gdb/doc/poke.texi
gdb/poke.c

index c7a3a8b43a4231269a7709ae65f8e8a1ad8f4bbf..8af56a224b82cd687d835326948de0a08fa485ea 100644 (file)
@@ -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
index e2833ed6bba9951cbcb61182b11e1ea66d32d393..9bb24236d2f7116062f903bc61f31af14f32a05f 100644 (file)
@@ -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;