Bug 14880 - In split register layouts, `up` results in assertion failure in value.c
Summary: In split register layouts, `up` results in assertion failure in value.c
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: tui (show other bugs)
Version: 7.5
: P2 minor
Target Milestone: 7.6
Assignee: Pedro Alves
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-11-26 21:33 UTC by Miles Yucht
Modified: 2013-06-28 12:44 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Executable which breaks gdb when trying to move up the stack frame in register split layouts (331.64 KB, application/octet-stream)
2012-11-26 21:33 UTC, Miles Yucht
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Miles Yucht 2012-11-26 21:33:22 UTC
Created attachment 6756 [details]
Executable which breaks gdb when trying to move up the stack frame in register split layouts

In the TUI split register layouts, running the command 'up' results in the following error:

(gdb) up
value.c:549: internal-error: value_available_contents_eq: Assertion `!val1->lazy && !val2->lazy' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) 

At this point, I'm offered the chance to quit the debugging session and to create a core dump of gdb.

This only happens in the asm/register or source/register split layouts; the behavior is normal with the other layouts.

To reproduce, run the following commands:
$ gdb p2
(gdb) b main
(gdb) r
(gdb) s (until you have moved into the addvec function source)
(gdb) layout p
(gdb) up

This has happened on other files as well. In addition, p2 and its libraries (statically linked) were compiled using gcc.

$ uname -a
Linux miles 3.5.6-1-ARCH #1 SMP PREEMPT Sun Oct 7 19:30:49 CEST 2012 x86_64 GNU/Linux

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /build/src/gcc-4.7.2/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --enable-libstdcxx-time --enable-gnu-unique-object --enable-linker-build-id --with-ppl --enable-cloog-backend=isl --disable-ppl-version-check --disable-cloog-version-check --enable-lto --enable-gold --enable-ld=default --enable-plugin --with-plugin-ld=ld.gold --with-linker-hash-style=gnu --enable-multilib --disable-libssp --disable-build-with-cxx --disable-build-poststage1-with-cxx --enable-checking=release
Thread model: posix
gcc version 4.7.2 (GCC)

$ gdb --version
GNU gdb (GDB) 7.5
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Comment 1 Andreas Kaufmann 2013-06-28 08:34:23 UTC
I hit this issue with gdb 7.6 as well.
Comment 2 Pedro Alves 2013-06-28 11:33:18 UTC
Reproducible with current mainline too:

(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
Comment 3 Pedro Alves 2013-06-28 11:35:32 UTC
  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);

That's obviously no longer true.
Comment 4 Sourceware Commits 2013-06-28 12:36:49 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	palves@sourceware.org	2013-06-28 12:36:48

Modified files:
	gdb            : ChangeLog value.c value.h 
	gdb/tui        : tui-regs.c 

Log message:
	[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.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&r1=1.15758&r2=1.15759
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/value.c.diff?cvsroot=src&r1=1.169&r2=1.170
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/value.h.diff?cvsroot=src&r1=1.219&r2=1.220
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/tui/tui-regs.c.diff?cvsroot=src&r1=1.48&r2=1.49
Comment 5 Sourceware Commits 2013-06-28 12:39:02 UTC
CVSROOT:	/cvs/src
Module name:	src
Branch: 	gdb_7_6-branch
Changes by:	palves@sourceware.org	2013-06-28 12:39:00

Modified files:
	gdb            : ChangeLog value.c value.h 
	gdb/tui        : tui-regs.c 

Log message:
	[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.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&only_with_tag=gdb_7_6-branch&r1=1.15260.2.56&r2=1.15260.2.57
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/value.c.diff?cvsroot=src&only_with_tag=gdb_7_6-branch&r1=1.167&r2=1.167.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/value.h.diff?cvsroot=src&only_with_tag=gdb_7_6-branch&r1=1.218&r2=1.218.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/tui/tui-regs.c.diff?cvsroot=src&only_with_tag=gdb_7_6-branch&r1=1.48&r2=1.48.2.1
Comment 6 Pedro Alves 2013-06-28 12:44:06 UTC
Fix will be in 7.6.1.