This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

src/gdb ChangeLog ada-lang.c value.c value.h t ...


CVSROOT:	/cvs/src
Module name:	src
Changes by:	brobecke@sourceware.org	2012-03-16 17:55:45

Modified files:
	gdb            : ChangeLog ada-lang.c value.c value.h 
	gdb/testsuite  : ChangeLog 
Added files:
	gdb/testsuite/gdb.ada: set_pckd_arr_elt.exp 
	gdb/testsuite/gdb.ada/set_pckd_arr_elt: foo.adb pck.adb pck.ads 

Log message:
	[Ada] Crash when trying to set value of packed array element
	
	Consider the following declaration:
	
	type Small is new Integer range 0 .. 2 ** 4 - 1;
	type Simple_Array is array (1 .. 4) of Small;
	pragma Pack (Simple_Array);
	
	SA : Simple_Array := (1, 2, 3, 4);
	
	Trying to change the value of one of the elements in the packed array
	causes the debugger to crash:
	
	(gdb) set sa(3) := 9
	[1]    4880 segmentation fault  gdb -q foo
	
	The circumstances leading to the crash are as follow:
	
	. ada_evaluate_subexp creates a value corresponding to "sa(3)".
	
	. ada_evaluate_subexp then tries to assign 9 to this value, and
	for this calls value_assign (via ada_value_assign).
	
	. Because the array is packed, the destination value is 3 bits long,
	and as a result, value_assign uses the parent to determine that
	element byte address and offset:
	
	| if (value_bitsize (toval))
	|   {
	|     struct value *parent = value_parent (toval);
	|
	|     changed_addr = value_address (parent) + value_offset (toval);
	
	The destination value (corresponding to "sa(3)") was incorrectly created
	by ada-lang.c:ada_value_primitive_packed_val, because the "parent" was
	left as NULL. So, when we try to dereference it to get the parent address,
	GDB crashed.
	
	The first part of the fix therefore consists in setting that field.
	This required the addition of a new "setter" in value.[hc].  It fixes
	the crash, but is still not sufficient for the assignment to actually
	work.
	
	The second part of the problem came from the fact that value_assign
	seems to expect the "child"'s address to be equal to the parent's address,
	with the difference being the offset. Unfortunately, this requirement was
	not followed by ada_value_primitive_packed_val, so the second part of
	the fix consisted in fixing that.
	
	Still, this was not sufficient, because it caused a regression when
	trying to perform an aggregate assignment of a packed array of packed
	record.  The key element here is the nesting of packed entities.
	Looking at the way ada_value_primitive_packed_val creates the value
	of each sub-component, one can see that the value's offset is set
	to the offset compared to the start of the parent. This was meant to
	match what value_primitive_field does as well.
	
	So, with our array of records, if the record offset was 2, and if
	the field we're interested in that record is at offset 1, the record
	value's offset would be set to 2, and the field value's offset would
	be set to 1. But the address for both values would be left to the
	array's address. This is where things start breaking down, because
	the value_address function for our field value would return the
	address of the array + 1, instead of + 3.
	
	This is what causes the final issue, here, because ada-lang.c's
	value_assign_to_component needs to compute the offset of the
	subcomponent compared to the top-level aggregate's start address
	(the array in our case). And it does so by subtracting the array's
	address from the sub-component's address.  When you have two levels
	of packed components, and the mid-level component is at an offset of
	the top-level component, things didn't work, because the component's
	address was miscomputed (the parent's offset is missing).
	
	The fix consists is fixing value_address to match the work done by
	value_primitive_field (where we ignore the parent's offset).
	
	gdb/ChangeLog:
	
	* value.h (set_value_parent): Add declaration.
	* value.c (set_value_parent): New function.
	(value_address): If VALUE->PARENT is not NULL, then use it as
	the base address instead of VALUE->LOCATION.address.
	* ada-lang.c (ada_value_primitive_packed_val): Keep V's address
	the same as OBJ's address.  Adjust V's offset accordingly.
	Set V's parent.
	
	gdb/testsuite/ChangeLog:
	
	* gdb.ada/set_pckd_arr_elt: New testcase.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&r1=1.14020&r2=1.14021
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ada-lang.c.diff?cvsroot=src&r1=1.349&r2=1.350
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/value.c.diff?cvsroot=src&r1=1.154&r2=1.155
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/value.h.diff?cvsroot=src&r1=1.198&r2=1.199
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/ChangeLog.diff?cvsroot=src&r1=1.3141&r2=1.3142
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.ada/set_pckd_arr_elt.exp.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.ada/set_pckd_arr_elt/foo.adb.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.ada/set_pckd_arr_elt/pck.adb.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.ada/set_pckd_arr_elt/pck.ads.diff?cvsroot=src&r1=NONE&r2=1.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]