[PR tui/14880] Fetch values before comparing their contents.

PR tui/14880 shows a reproducer that triggers this assertion:

  int
  value_available_contents_eq (const struct value *val1, int offset1,
  			     const struct value *val2, int offset2,
  			     int length)
  {
    int idx1 = 0, idx2 = 0;

    /* This routine is used by printing routines, where we should
       already have read the value.  Note that we only know whether a
       value chunk is available if we've tried to read it.  */
    gdb_assert (!val1->lazy && !val2->lazy);

(top-gdb) bt
#0  internal_error (file=0x88a26c "../../src/gdb/value.c", line=549, string=0x88a220 "%s: Assertion `%s' failed.") at ../../src/gdb/utils.c:844
#1  0x000000000057b9cd in value_available_contents_eq (val1=0x10fa900, offset1=0, val2=0x10f9e10, offset2=0, length=8) at ../../src/gdb/value.c:549
#2  0x00000000004fd756 in tui_get_register (frame=0xd5c430, data=0x109a548, regnum=0, changedp=0x109a560) at ../../src/gdb/tui/tui-regs.c:736
#3  0x00000000004fd111 in tui_check_register_values (frame=0xd5c430) at ../../src/gdb/tui/tui-regs.c:521
#4  0x0000000000501884 in tui_check_data_values (frame=0xd5c430) at ../../src/gdb/tui/tui-windata.c:234
#5  0x00000000004f976f in tui_selected_frame_level_changed_hook (level=1) at ../../src/gdb/tui/tui-hooks.c:222
#6  0x00000000006f0681 in select_frame (fi=0xd5c430) at ../../src/gdb/frame.c:1490
#7  0x00000000005dd94b in up_silently_base (count_exp=0x0) at ../../src/gdb/stack.c:2268
#8  0x00000000005dd985 in up_command (count_exp=0x0, from_tty=1) at ../../src/gdb/stack.c:2280
#9  0x00000000004dc5cf in do_cfunc (c=0xd3f720, args=0x0, from_tty=1) at ../../src/gdb/cli/cli-decode.c:113
#10 0x00000000004df664 in cmd_func (cmd=0xd3f720, args=0x0, from_tty=1) at ../../src/gdb/cli/cli-decode.c:1888
#11 0x00000000006e43e1 in execute_command (p=0xc7e6c2 "", from_tty=1) at ../../src/gdb/top.c:489

The fix is to fetch the value before comparing the contents.  The
comment additions to value.h explain why it can't be
value_available_contents_eq itself that fetches the contents.

Tested on x86_64 Fedora 17.

gdb/
2013-06-28  Pedro Alves  <palves@redhat.com>

	PR tui/14880
	* tui/tui-regs.c (tui_get_register): Fetch register value contents
	before checking whether they're available.
	* value.c (value_available_contents_eq): Change comment.
	* value.h (value_available_contents_eq): Expand comment.
This commit is contained in:
Pedro Alves 2013-06-28 12:36:48 +00:00
parent 257b6bec77
commit 4eb5910882
4 changed files with 22 additions and 4 deletions

View file

@ -1,3 +1,11 @@
2013-06-28 Pedro Alves <palves@redhat.com>
PR tui/14880
* tui/tui-regs.c (tui_get_register): Fetch value contents before
checking if they're available.
* value.c (value_available_contents_eq): Change comment.
* value.h (value_available_contents_eq): Expand comment.
2013-06-27 Tom Tromey <tromey@redhat.com>
* target.c (find_run_target): Remove.

View file

@ -732,6 +732,13 @@ tui_get_register (struct frame_info *frame,
struct gdbarch *gdbarch = get_frame_arch (frame);
int size = register_size (gdbarch, regnum);
/* We only know whether a value chunk is available if we've
tried to read it. */
if (value_lazy (data->value))
value_fetch_lazy (data->value);
if (value_lazy (old_val))
value_fetch_lazy (old_val);
if (value_optimized_out (data->value) != value_optimized_out (old_val)
|| !value_available_contents_eq (data->value, 0,
old_val, 0, size))

View file

@ -543,9 +543,7 @@ value_available_contents_eq (const struct value *val1, int offset1,
{
int idx1 = 0, idx2 = 0;
/* This routine is used by printing routines, where we should
already have read the value. Note that we only know whether a
value chunk is available if we've tried to read it. */
/* See function description in value.h. */
gdb_assert (!val1->lazy && !val2->lazy);
while (length > 0)

View file

@ -463,7 +463,12 @@ extern void mark_value_bytes_unavailable (struct value *value,
value_available_contents_eq(val, 4, val, 12, 2) => 1
value_available_contents_eq(val, 4, val, 12, 4) => 0
value_available_contents_eq(val, 3, val, 4, 4) => 0
*/
We only know whether a value chunk is available if we've tried to
read it. As this routine is used by printing routines, which may
be printing values in the value history, long after the inferior is
gone, it works with const values. Therefore, this routine must not
be called with lazy values. */
extern int value_available_contents_eq (const struct value *val1, int offset1,
const struct value *val2, int offset2,