Go to file
Joel Brobecker 53ba833325 [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.
2012-03-16 17:55:45 +00:00
bfd * bfd/elf32-arm.c (elf32_arm_attributes_accept_div): New function. 2012-03-16 15:15:14 +00:00
binutils PR binutils/3807 2012-03-13 00:41:22 +00:00
config config/: 2011-12-20 17:01:30 +00:00
cpu cpu/ 2012-02-27 06:57:57 +00:00
elfcpp elfcpp/ 2012-03-13 00:13:08 +00:00
etc
gas * gas/config/tc-arm.c (aeabi_set_public_attributes): Correct 2012-03-16 14:02:33 +00:00
gdb [Ada] Crash when trying to set value of packed array element 2012-03-16 17:55:45 +00:00
gold 2012-03-15 Doug Kwan <dougkwan@google.com> 2012-03-15 18:24:06 +00:00
gprof 2012-03-06 Tristan Gingold <gingold@adacore.com> 2012-03-06 13:54:59 +00:00
include include/ 2012-03-15 12:58:48 +00:00
intl
ld * gas/config/tc-arm.c (aeabi_set_public_attributes): Correct 2012-03-16 14:02:33 +00:00
libdecnumber config/: 2011-12-20 17:01:30 +00:00
libiberty merge from gcc 2012-03-08 00:01:31 +00:00
opcodes * ppc-dis.c (PPC_OPC_SEGS, PPC_OP_TO_SEG): Delete. 2012-03-16 12:14:32 +00:00
readline * signals.c (_rl_block_sigwinch, _rl_release_sigwinch): Add 2012-02-24 17:14:43 +00:00
sim sim: ppc: fix compilation on AIX 7.1 due to st_pad name collisions 2012-03-14 05:04:18 +00:00
texinfo
.cvsignore
.gitignore
ChangeLog * configure.ac (enable_libgomp): Remove *-*-irix6*. 2012-03-15 14:13:32 +00:00
compile
config-ml.in
config.guess
config.rpath
config.sub * config.sub: Update to version 2011-10-29 (added rl78) 2011-11-02 00:56:53 +00:00
configure * configure.ac (enable_libgomp): Remove *-*-irix6*. 2012-03-15 14:13:32 +00:00
configure.ac * configure.ac (enable_libgomp): Remove *-*-irix6*. 2012-03-15 14:13:32 +00:00
COPYING
COPYING3
COPYING3.LIB
COPYING.LIB
COPYING.LIBGLOSS 2012-03-09 Jeff Johnston <jjohnstn@redhat.com> 2012-03-09 20:31:34 +00:00
COPYING.NEWLIB 2012-03-09 Jeff Johnston <jjohnstn@redhat.com> 2012-03-09 20:31:34 +00:00
depcomp
djunpack.bat
install-sh
libtool.m4
lt~obsolete.m4
ltgcc.m4
ltmain.sh
ltoptions.m4
ltsugar.m4
ltversion.m4
MAINTAINERS
Makefile.def 2011-11-09 Roland McGrath <mcgrathr@google.com> 2011-11-09 18:57:30 +00:00
Makefile.in 2011-11-09 Roland McGrath <mcgrathr@google.com> 2011-11-09 18:57:30 +00:00
Makefile.tpl 2011-11-09 Roland McGrath <mcgrathr@google.com> 2011-11-09 18:57:30 +00:00
makefile.vms
missing
mkdep
mkinstalldirs
move-if-change
README
README-maintainer-mode
setup.com
src-release
symlink-tree
ylwrap

		   README for GNU development tools

This directory contains various GNU compilers, assemblers, linkers, 
debuggers, etc., plus their support routines, definitions, and documentation.

If you are receiving this as part of a GDB release, see the file gdb/README.
If with a binutils release, see binutils/README;  if with a libg++ release,
see libg++/README, etc.  That'll give you info about this
package -- supported targets, how to use it, how to report bugs, etc.

It is now possible to automatically configure and build a variety of
tools with one command.  To build all of the tools contained herein,
run the ``configure'' script here, e.g.:

	./configure 
	make

To install them (by default in /usr/local/bin, /usr/local/lib, etc),
then do:
	make install

(If the configure script can't determine your type of computer, give it
the name as an argument, for instance ``./configure sun4''.  You can
use the script ``config.sub'' to test whether a name is recognized; if
it is, config.sub translates it to a triplet specifying CPU, vendor,
and OS.)

If you have more than one compiler on your system, it is often best to
explicitly set CC in the environment before running configure, and to
also set CC when running make.  For example (assuming sh/bash/ksh):

	CC=gcc ./configure
	make

A similar example using csh:

	setenv CC gcc
	./configure
	make

Much of the code and documentation enclosed is copyright by
the Free Software Foundation, Inc.  See the file COPYING or
COPYING.LIB in the various directories, for a description of the
GNU General Public License terms under which you can copy the files.

REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info
on where and how to report problems.