Avoid crash when "compile" expression uses cooked register

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.
This commit is contained in:
Tom Tromey 2021-01-23 12:20:11 -07:00
parent 3637a558a5
commit b10bae1875
2 changed files with 22 additions and 2 deletions

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

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