[PR tui/14880] Fetch values before comparing their contents.
authorPedro Alves <palves@redhat.com>
Fri, 28 Jun 2013 12:36:48 +0000 (12:36 +0000)
committerPedro Alves <palves@redhat.com>
Fri, 28 Jun 2013 12:36:48 +0000 (12:36 +0000)
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.

gdb/ChangeLog
gdb/tui/tui-regs.c
gdb/value.c
gdb/value.h

index 13b705787fe3aa2d1ddaec29d7d908534972f539..faaaf506ebac82d495427f0d4d795f3e6243fe1d 100644 (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.
index 7f64a2b3cb6c0ba506c2ba63f1e4b6e7b7c9f2c5..975173a326e778b15a3c1b16832cee1de15c2097 100644 (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))
index ee3c9983036b65a4f9a5f3a445cad5fb8d0343d6..fae8b9847112cb1dc11f86c908e5bcfc59519b05 100644 (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)
index 4e839d3939fbe97c85774b4cfde02d315e4a8bbd..8a66aa48d1dc9f7f1fffb21a15163b7d715b347d 100644 (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,
This page took 0.045484 seconds and 4 git commands to generate.