[RFC] setting the raw content of a register

Jerome Guitton
2012-05-22T14:37:04Z

When trying to set the raw content of a fp register, many users try
something like:

(gdb) set $f14 := 0xFFF0000000000050
(gdb) info registers $f14
f14 -4503599627370416.0 (raw 0xc32fffffffffff60)

Of course, GDB sets the value of $f14, not its raw content. Now
this can be worked around by writing the raw content in memory,
re-read it as a float and store the value into register f14. Quite
kludgy though, and it often hits some limitations of the interpreter
regarding floats (e.g. signs of NaN are lost).

Maybe the simplest solution would be to add a new command to set the
raw content of a register. Attached a first candidate implementation,
to give an idea of how it could look like. The name of the command
here is "set register", but I would be happy to change it.

(gdb) help set register
Write raw value into register
Usage: set register REGNAME VALUE.
(gdb) set register f14 0xFFF0000000000050
(gdb) info registers $f14
f14 NaN(0x000000050) (raw 0xfff0000000000050)

Of course this would need some documentation, a new testcase, and
maybe a new python command as well (?). But I'd like to have your
opinion on the general idea first.

gdb/ChangeLog:

* printcmd.c (set_register_command): New function.
(_initialize_printcmd): New command "set register".
---
gdb/printcmd.c | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 030a4f2..7080d0e 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -49,6 +49,8 @@
#include "charset.h"
#include "arch-utils.h"
#include "cli/cli-utils.h"
+#include "regcache.h"
+#include "user-regs.h"

#ifdef TUI
#include "tui/tui.h" /* For tui_active et al. */
@@ -1077,6 +1079,34 @@ output_command (char *exp, int from_tty)
}

static void
+set_register_command (char *exp, int from_tty)
+{
+ struct regcache *cache = get_current_regcache();
+ char *regname = exp, *exp2 = exp;
+ struct expression *expr;
+ struct cleanup *old_chain;
+ struct value *val, *reg;
+ int regnum;
+
+ exp2 = skip_to_space (exp);
+ if (*exp == '\0' || *exp2 == '\0')
+ error_no_arg (_("Two arguments required."));
+ *exp2 = '\0';
+ exp2 += 1;
+
+ regnum = user_reg_map_name_to_regnum (get_regcache_arch (cache),
+ regname, strlen (regname));
+ if (regnum == -1)
+ error (_("First argument must be a register."));
+
+ expr = parse_expression (exp2);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ val = evaluate_expression (expr);
+ regcache_raw_write_unsigned (cache, regnum, value_as_long (val));
+ do_cleanups (old_chain);
+}
+
+static void
set_command (char *exp, int from_tty)
{
struct expression *expr = parse_expression (exp);
@@ -2851,6 +2881,11 @@ variable in the program being debugged. EXP is any valid expression.\n\
This may usually be abbreviated to simply \"set\"."),
&setlist);

+ add_cmd ("register", class_vars, set_register_command, _("\
+Write raw value into register\n\
+Usage: set register REGNAME VALUE."),
+ &setlist);
+
c = add_com ("print", class_vars, print_command, _("\
Print value of expression EXP.\n\
Variables accessible are those of the lexical environment of the selected\n\
--
1.7.0.2