[Ada] problem printing negative integer values in packed arrays.
authorJoel Brobecker <brobecker@adacore.com>
Sat, 9 May 2015 00:11:35 +0000 (17:11 -0700)
committerJoel Brobecker <brobecker@adacore.com>
Fri, 15 May 2015 14:37:15 +0000 (07:37 -0700)
Consider the following declarations:

   type Signed_Small is new Integer range - (2 ** 5) .. (2 ** 5 - 1);
   type Signed_Simple_Array is array (1 .. 4) of Signed_Small;
   pragma Pack (Signed_Simple_Array);
   SSA : Signed_Simple_Array := (-1, 2, -3, 4);

GDB currently print its value incorrectly for the elements that
are negative:

    (gdb) print ssa
    $1 = (65535, 2, 1048573, 4)
    (gdb) print ssa(1)
    $2 = 65535
    (gdb) print ssa(2)
    $3 = 2
    (gdb) print ssa(3)
    $4 = 1048573
    (gdb) print ssa(4)
    $5 = 4

What happens is that the sign-extension is not working because
we're trying to do left shift with a negative count. In
ada_value_primitive_packed_val, we have a loop which populates
the extra bits of the target (unpacked) value, after extraction
of the data from the original (packed) value:

        while (ntarg > 0)
          {
            accum |= sign << accumSize;
            unpacked[targ] = accum & ~(~0L << HOST_CHAR_BIT);
!!! ->      accumSize -= HOST_CHAR_BIT;
            accum >>= HOST_CHAR_BIT;
            ntarg -= 1;
            targ += delta;
          }

At each iteration, accumSize gets decremented by HOST_CHAR_BIT,
which can easily cause it to become negative, particularly on
little endian targets, where accumSize is at most HOST_CHAR_BIT - 1.
This causes us to perform a left-shift operation with a negative
accumSize at the next loop iteration, which is undefined, and
acutally does not produce the effect we wanted (value left untouched)
when the code is compiled with GCC.

This patch fixes the issue by simply setting accumSize to zero
if negative.

gdb/ChangeLog:

        * ada-lang.c (ada_value_primitive_packed_val): Make sure
        accumSize is never negative.

gdb/testsuite/ChangeLog:

        * gdb.ada/pckd_neg: New testcase.

gdb/ChangeLog
gdb/ada-lang.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.ada/pckd_neg.exp [new file with mode: 0644]
gdb/testsuite/gdb.ada/pckd_neg/foo_o508_021.adb [new file with mode: 0644]
gdb/testsuite/gdb.ada/pckd_neg/pck.adb [new file with mode: 0644]
gdb/testsuite/gdb.ada/pckd_neg/pck.ads [new file with mode: 0644]

index 5fd5686617139e4fae00c789657a45a4346c291e..14929810ad4e39178653e183a8a86401d9bbd898 100644 (file)
@@ -1,3 +1,8 @@
+2015-05-15  Joel Brobecker  <brobecker@adacore.com>
+
+       * ada-lang.c (ada_value_primitive_packed_val): Make sure
+       accumSize is never negative.
+
 2015-05-14  Patrick Palka  <patrick@parcs.ath.cx>
 
        * tui/tui-command.c: Remove include of <ctype.h>.
index 3a00e5ba1b48754d0d9749b590019d9c65628723..e3fa3632dc81c6b7f5df5fe94139104f1122b04a 100644 (file)
@@ -2544,6 +2544,8 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr,
       accum |= sign << accumSize;
       unpacked[targ] = accum & ~(~0L << HOST_CHAR_BIT);
       accumSize -= HOST_CHAR_BIT;
+      if (accumSize < 0)
+       accumSize = 0;
       accum >>= HOST_CHAR_BIT;
       ntarg -= 1;
       targ += delta;
index db8f3ce83a27a6b407fdc2d432337a085c5e585a..cc2c1565b8dd95b714fd50290b28007e5e80abc6 100644 (file)
@@ -1,3 +1,7 @@
+2015-05-15  Joel Brobecker  <brobecker@adacore.com>
+
+       * gdb.ada/pckd_neg: New testcase.
+
 2015-05-13  Patrick Palka  <patrick@parcs.ath.cx>
 
        PR gdb/17820
diff --git a/gdb/testsuite/gdb.ada/pckd_neg.exp b/gdb/testsuite/gdb.ada/pckd_neg.exp
new file mode 100644 (file)
index 0000000..e03a11c
--- /dev/null
@@ -0,0 +1,44 @@
+# Copyright 2015 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "ada.exp"
+
+if { [skip_ada_tests] } { return -1 }
+
+standard_ada_testfile foo_o508_021
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
+    return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/foo_o508_021.adb]
+runto "foo_o508_021.adb:$bp_location"
+
+gdb_test "print SSA" \
+         "= \\(-1, 2, -3, 4\\)"
+
+gdb_test "print SSA(1)" \
+         "= -1"
+
+gdb_test "print SSA(2)" \
+         "= 2"
+
+gdb_test "print SSA(3)" \
+         "= -3"
+
+gdb_test "print SSA(4)" \
+         "= 4"
diff --git a/gdb/testsuite/gdb.ada/pckd_neg/foo_o508_021.adb b/gdb/testsuite/gdb.ada/pckd_neg/foo_o508_021.adb
new file mode 100644 (file)
index 0000000..4750b95
--- /dev/null
@@ -0,0 +1,22 @@
+--  Copyright (C) 2015 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+with Pck; use Pck;
+
+procedure Foo_O508_021 is
+   SSA : Signed_Simple_Array := (-1, 2, -3, 4);
+begin
+   Update_Signed_Small (SSA (3));  -- STOP
+end Foo_O508_021;
diff --git a/gdb/testsuite/gdb.ada/pckd_neg/pck.adb b/gdb/testsuite/gdb.ada/pckd_neg/pck.adb
new file mode 100644 (file)
index 0000000..2d3b6c5
--- /dev/null
@@ -0,0 +1,21 @@
+--  Copyright (C) 2015 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package body Pck is
+   procedure Update_Signed_Small (S : in out Signed_Small) is
+   begin
+      null;
+   end Update_Signed_Small;
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/pckd_neg/pck.ads b/gdb/testsuite/gdb.ada/pckd_neg/pck.ads
new file mode 100644 (file)
index 0000000..c463bbc
--- /dev/null
@@ -0,0 +1,22 @@
+--  Copyright (C) 2015 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package Pck is
+   type Signed_Small is new Integer range - (2 ** 5) .. (2 ** 5 - 1);
+   type Signed_Simple_Array is array (1 .. 4) of Signed_Small;
+   pragma Pack (Signed_Simple_Array);
+
+   procedure Update_Signed_Small (S : in out Signed_Small);
+end Pck;