Avoid crash when "compile" expression uses cooked register
authorTom Tromey <tom@tromey.com>
Sat, 23 Jan 2021 19:20:11 +0000 (12:20 -0700)
committerTom Tromey <tom@tromey.com>
Sun, 24 Jan 2021 03:33:25 +0000 (20:33 -0700)
If the "compile" command is used with an expression that happens to
require a cooked register, then GDB can crash.  This patch does not
fix the bug, but at least turns the crash into an error instead.

2021-01-23  Tom Tromey  <tom@tromey.com>

PR compile/25575
* compile/compile-loc2c.c (note_register): New function.
(pushf_register_address, pushf_register): Use it.

gdb/ChangeLog
gdb/compile/compile-loc2c.c

index 8fa20fae30fa926a8726023c9f900771f817680d..9f9681fef84389d14f22e29b43225258725737ec 100644 (file)
@@ -1,3 +1,9 @@
+2021-01-23  Tom Tromey  <tom@tromey.com>
+
+       PR compile/25575
+       * compile/compile-loc2c.c (note_register): New function.
+       (pushf_register_address, pushf_register): Use it.
+
 2021-01-23  Tom Tromey  <tom@tromey.com>
 
        * symtab.h (struct symbol_computed_ops) <generate_c_location>:
index ee9595c78edb0eb78f0174633e3648a997e6a5de..ef819799eb49b6d650cd19b57d00b193bfecc083 100644 (file)
@@ -505,6 +505,20 @@ print_label (string_file *stream, unsigned int scope, int target)
   stream->printf ("__label_%u_%s", scope, pulongest (target));
 }
 
+/* Note that a register was used.  */
+
+static void
+note_register (int regnum, std::vector<bool> &registers_used)
+{
+  gdb_assert (regnum >= 0);
+  /* If the expression uses a cooked register, then we currently can't
+     compile it.  We would need a gdbarch method to handle this
+     situation.  */
+  if (regnum >= registers_used.size ())
+    error (_("Expression uses \"cooked\" register and cannot be compiled."));
+  registers_used[regnum] = true;
+}
+
 /* Emit code that pushes a register's address on the stack.
    REGISTERS_USED is an out parameter which is updated to note which
    register was needed by this expression.  */
@@ -516,7 +530,7 @@ pushf_register_address (int indent, string_file *stream,
 {
   std::string regname = compile_register_name_mangled (gdbarch, regnum);
 
-  registers_used[regnum] = true;
+  note_register (regnum, registers_used);
   pushf (indent, stream,
         "(" GCC_UINTPTR ") &" COMPILE_I_SIMPLE_REGISTER_ARG_NAME "->%s",
         regname.c_str ());
@@ -534,7 +548,7 @@ pushf_register (int indent, string_file *stream,
 {
   std::string regname = compile_register_name_mangled (gdbarch, regnum);
 
-  registers_used[regnum] = true;
+  note_register (regnum, registers_used);
   if (offset == 0)
     pushf (indent, stream, COMPILE_I_SIMPLE_REGISTER_ARG_NAME "->%s",
           regname.c_str ());