gdb/poke: Support the $reg::REGNAME syntax

Make it possible to use $reg::REGNAME to access the content of a
register from poke expressions.
This commit is contained in:
Lancelot SIX
2022-09-19 12:30:12 +01:00
committed by Lancelot SIX
parent 21c2659b8e
commit d734c63af7
2 changed files with 94 additions and 0 deletions

View 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

View 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;