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]

[binutils-gdb] improved error message when getting an exception printing a variable


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=eccab96d54a9455557d3c4d5bff431f6e526d0b7

commit eccab96d54a9455557d3c4d5bff431f6e526d0b7
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Sun Dec 17 22:39:33 2017 -0500

    improved error message when getting an exception printing a variable
    
    Consider the following Ada code defining a global variable whose
    type is an array of static bounds (1 .. 2), but where its elements
    are a variant record whose size is not statically known:
    
        type Ints is array (Natural range <>) of Integer;
        type Bounded_Ints (Max_Size : Natural) is record
           Length : Natural := 0;
           Objs   : Ints (1 .. Max_Size);
        end record;
    
        type Ints_Doubled is array (1 .. 2) of Bounded_Ints (Idem (0));
    
        Global : Ints_Doubled;
    
    When compiling this program at -O2 using a GCC-6.4-based compiler
    on x86_64-linux, trying to print the value of that global variable
    yields:
    
        (gdb) p global
        $1 =
    
    Let's look at the debugging info, which starts with the global
    variable itself...
    
            .uleb128 0x19   # (DIE (0x25e) DW_TAG_variable)
            .long   .LASF32 # DW_AT_name: "fd__global"
            .long   0x273   # DW_AT_type
    
    ... its type is a reference to a typedef ...
    
            .uleb128 0x14   # (DIE (0x273) DW_TAG_reference_type)
            .byte   0x8     # DW_AT_byte_size
            .long   0x202   # DW_AT_type
            [...]
            .uleb128 0x15   # (DIE (0x202) DW_TAG_typedef)
            .long   .LASF19 # DW_AT_name: "fd__ints_doubled"
            .long   0x20d   # DW_AT_type
    
    ... of an array (1..2) ...
    
            .uleb128 0x2    # (DIE (0x20d) DW_TAG_array_type)
            .long   .LASF19 # DW_AT_name: "fd__ints_doubled"
            .long   0x15b   # DW_AT_type
            .long   0x221   # DW_AT_sibling
            .uleb128 0x16   # (DIE (0x21a) DW_TAG_subrange_type)
            .long   0x40    # DW_AT_type
            .sleb128 2      # DW_AT_upper_bound
            .byte   0       # end of children of DIE 0x20d
    
    ... of a struct whose name is fd__Tints_doubledC:
    
            .uleb128 0x10   # (DIE (0x15b) DW_TAG_structure_type)
            .long   .LASF11 # DW_AT_name: "fd__Tints_doubledC"
            .long   0x1e4   # DW_AT_GNAT_descriptive_type
                            # DW_AT_artificial
            .long   0x1e4   # DW_AT_sibling
            .uleb128 0x7    # (DIE (0x16a) DW_TAG_member)
            .long   .LASF4  # DW_AT_name: "max_size"
            [snip]
    
    The error occurs while Ada evaluator is trying to "fix"
    the element type inside the array, so as to determine its actual
    size. For that, it searches for a parallel "XVZ" variable,
    which, when found, contains the object's actual size.
    
    Unfortunately in our case, the variable exists but has been
    optimized out, as seen by the presence of a variable DIE in
    the debugging info, but with no address attribute:
    
            .uleb128 0x18   # (DIE (0x24e) DW_TAG_variable)
            .long   .LASF31 # DW_AT_name: "fd__Tints_doubledC___XVZ"
            .long   0x257   # DW_AT_type
                            # DW_AT_artificial
    
    Discussing this with some members of AdaCore's compiler team,
    it is expected that the optimizer can get rid of this variable,
    and we don't want to pessimize the code just to improve debuggability,
    since -O2 is about performance. So, the idea of this patch is
    not to make it work, but provide a bit more information to help
    users understand what kind of error is preventing GDB from being
    able to print the variable's value.
    
    The first hurdle we had to clear was the fact that ada_val_print
    traps all exceptions (including QUIT ones!), and does so completly
    silently. So, the fix was to add a trace of the exception being
    generated. While doing so, we fix an old XXX/FIXME by only catching
    errors, letting QUIT exceptions go through.
    
    Once this is done, we now get an error message, which gives a first
    clue as to what was happening:
    
        (gdb) p fd.global
        $1 = <error reading variable: value has been optimized out>
    
    However, it would be more useful to know which value it was
    that was optimized out. For that purpose, we enhanced
    ada-lang.c::ada_to_fixed_type_1 so as to re-throw the error
    with a message which indicates which variable we failed to read.
    
    With those changes, the new output is now:
    
        (gdb) p fd.global
        $1 = <error reading variable: unable to read value of fd__Tints_doubledC___XVZ (value has been optimized out)>
    
    gdb/ChangeLog:
    
            * ada-lang.c (ada_to_fixed_type_1): Rethrow errors with
            a more detailed exception message when getting an exception
            while trying to read the value of an XVZ variable.
            * ada-valprint.c (ada_val_print): Only catch RETURN_MASK_ERROR
            exceptions.  Print an error message when an exception is caught.
    
    gdb/testsuite/ChangeLog:
    
            * gdb.dwarf2/ada-valprint-error.c: New file.
            * gdb.dwarf2/ada-valprint-error.exp: New file.
    
    Tested on x86_64-linux

Diff:
---
 gdb/ChangeLog                                   |   8 ++
 gdb/ada-lang.c                                  |  21 ++++-
 gdb/ada-valprint.c                              |   6 +-
 gdb/testsuite/ChangeLog                         |   5 ++
 gdb/testsuite/gdb.dwarf2/ada-valprint-error.c   |  23 +++++
 gdb/testsuite/gdb.dwarf2/ada-valprint-error.exp | 115 ++++++++++++++++++++++++
 6 files changed, 173 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5e65e5f..4023472 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2017-12-18  Joel Brobecker  <brobecker@adacore.com>
 
+	* ada-lang.c (ada_to_fixed_type_1): Rethrow errors with
+	a more detailed exception message when getting an exception
+	while trying to read the value of an XVZ variable.
+	* ada-valprint.c (ada_val_print): Only catch RETURN_MASK_ERROR
+	exceptions.  Print an error message when an exception is caught.
+
+2017-12-18  Joel Brobecker  <brobecker@adacore.com>
+
 	* ada-lang.c (assign_component): Strip any TYPE_CODE_TYPEDEF
 	layer from lhs' type.
 	(assign_aggregate): Likewise.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 14a0bd6..dad2b17 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -9101,11 +9101,28 @@ ada_to_fixed_type_1 (struct type *type, const gdb_byte *valaddr,
             const char *name = ada_type_name (fixed_record_type);
             char *xvz_name
 	      = (char *) alloca (strlen (name) + 7 /* "___XVZ\0" */);
+	    bool xvz_found = false;
             LONGEST size;
 
             xsnprintf (xvz_name, strlen (name) + 7, "%s___XVZ", name);
-            if (get_int_var_value (xvz_name, size)
-		&& TYPE_LENGTH (fixed_record_type) != size)
+	    TRY
+	      {
+		xvz_found = get_int_var_value (xvz_name, size);
+	      }
+	    CATCH (except, RETURN_MASK_ERROR)
+	      {
+		/* We found the variable, but somehow failed to read
+		   its value.  Rethrow the same error, but with a little
+		   bit more information, to help the user understand
+		   what went wrong (Eg: the variable might have been
+		   optimized out).  */
+		throw_error (except.error,
+			     _("unable to read value of %s (%s)"),
+			     xvz_name, except.message);
+	      }
+	    END_CATCH
+
+            if (xvz_found && TYPE_LENGTH (fixed_record_type) != size)
               {
                 fixed_record_type = copy_type (fixed_record_type);
                 TYPE_LENGTH (fixed_record_type) = size;
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index 91dc301..b4a48ce 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -1168,16 +1168,16 @@ ada_val_print (struct type *type,
 	       struct value *val,
 	       const struct value_print_options *options)
 {
-
-  /* XXX: this catches QUIT/ctrl-c as well.  Isn't that busted?  */
   TRY
     {
       ada_val_print_1 (type, embedded_offset, address,
 		       stream, recurse, val, options,
 		       current_language);
     }
-  CATCH (except, RETURN_MASK_ALL)
+  CATCH (except, RETURN_MASK_ERROR)
     {
+      fprintf_filtered (stream, _("<error reading variable: %s>"),
+			except.message);
     }
   END_CATCH
 }
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index c074186..51c9864 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,10 @@
 2017-12-18  Joel Brobecker  <brobecker@adacore.com>
 
+	* gdb.dwarf2/ada-valprint-error.c: New file.
+	* gdb.dwarf2/ada-valprint-error.exp: New file.
+
+2017-12-18  Joel Brobecker  <brobecker@adacore.com>
+
 	* gdb.ada/assign_arr: New testcase.
 
 2017-12-18  Xavier Roirand  <roirand@adacore.com>
diff --git a/gdb/testsuite/gdb.dwarf2/ada-valprint-error.c b/gdb/testsuite/gdb.dwarf2/ada-valprint-error.c
new file mode 100644
index 0000000..4f04ab7
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/ada-valprint-error.c
@@ -0,0 +1,23 @@
+/* Copyright 2017 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/>.  */
+
+int buffer[] = {0, 0};
+void *fd__global = &buffer;
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/ada-valprint-error.exp b/gdb/testsuite/gdb.dwarf2/ada-valprint-error.exp
new file mode 100644
index 0000000..192b0cb
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/ada-valprint-error.exp
@@ -0,0 +1,115 @@
+# Copyright 2017 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 dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+    return 0
+}
+
+standard_testfile ada-valprint-error.c ada-valprint-error-dw.S
+
+# We need to know the size of integer and address types in order
+# to write some of the debugging info we'd like to generate.
+#
+# For that, we ask GDB by debugging our ada-valprint-error.c program.
+# Any program would do, but since we already have ada-valprint-error.c
+# specifically for this testcase, might as well use that.
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    untested ${testfile}.exp
+    return -1
+}
+
+# Make some DWARF for the test.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    cu {} {
+ 	DW_TAG_compile_unit {
+                {DW_AT_language @DW_LANG_Ada95}
+                {DW_AT_name     fd.adb}
+                {DW_AT_comp_dir /tmp}
+        } {
+	    declare_labels array_elt_label integer_label array_label \
+                typedef_label ref_type_label
+            set ptr_size [get_sizeof "void *" 96]
+            set int_size [get_sizeof "int" 4]
+
+            # A structure with no size attribute, to mimick structures
+            # in Ada that have a dynamic size...
+            array_elt_label: structure_type {
+                {name fd__Tints_doubledC}
+                {artificial 1 DW_FORM_flag_present}
+            }
+
+            # ... and a corresponding XVZ variable, supposed to be there
+            # to provide the actual size.  Except that, in this case,
+            # the variable has no address, to simulate the fact that
+            # it has been optimized out (which the compiler can do,
+            # even if it at the expense of debuggability).
+            DW_TAG_variable {
+                {name fd__Tints_doubledC___XVZ}
+                {DW_AT_type :$integer_label}
+                {artificial 1 DW_FORM_flag_present}
+            }
+
+            integer_label: DW_TAG_base_type {
+                {DW_AT_byte_size $int_size DW_FORM_sdata}
+                {DW_AT_encoding  @DW_ATE_signed}
+                {DW_AT_name      integer}
+            }
+
+	    array_label: DW_TAG_array_type {
+		{DW_AT_name fd__ints_doubled}
+		{DW_AT_type :$array_elt_label}
+	    } {
+		DW_TAG_subrange_type {
+		    {DW_AT_type        :$integer_label}
+		    {DW_AT_upper_bound 2 DW_FORM_data1}
+		}
+	    }
+
+            typedef_label: DW_TAG_typedef {
+                {DW_AT_name fd__ints_doubled}
+                {DW_AT_type :$array_label}
+            }
+
+            ref_type_label: DW_TAG_reference_type {
+                {DW_AT_byte_size $ptr_size DW_FORM_sdata}
+                {DW_AT_type :$typedef_label}
+            }
+
+            DW_TAG_variable {
+                {name fd__global}
+                {DW_AT_type :$ref_type_label}
+                {DW_AT_location {
+                    DW_OP_addr [gdb_target_symbol fd__global]
+                } SPECIAL_expr}
+                {external 1 flag}
+            }
+
+	}
+    }
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} \
+	  [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+gdb_test_no_output "set language ada"
+
+gdb_test "print fd.global" \
+         " = <error reading variable: unable to read value of fd__Tints_doubledC___XVZ \\(value has been optimized out\\)>"


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