public inbox for gdb-testers@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] gdb: Dynamic string length support
@ 2019-12-02  0:49 gdb-buildbot
  2019-12-02  0:49 ` Failures on Ubuntu-Aarch64-native-extended-gdbserver-m64, branch master gdb-buildbot
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: gdb-buildbot @ 2019-12-02  0:49 UTC (permalink / raw)
  To: gdb-testers

*** TEST RESULTS FOR COMMIT 216a7e6b9e5d2b279276f3bd8c11145a7d9b59ac ***

commit 216a7e6b9e5d2b279276f3bd8c11145a7d9b59ac
Author:     Andrew Burgess <andrew.burgess@embecosm.com>
AuthorDate: Fri Nov 29 00:14:35 2019 +0000
Commit:     Andrew Burgess <andrew.burgess@embecosm.com>
CommitDate: Sun Dec 1 22:31:32 2019 +0000

    gdb: Dynamic string length support
    
    Add support for strings with dynamic length using the DWARF attribute
    DW_AT_string_length.
    
    Currently gFortran generates DWARF for some strings that make use of
    DW_AT_string_length like this:
    
     <1><2cc>: Abbrev Number: 20 (DW_TAG_string_type)
        <2cd>   DW_AT_string_length: 5 byte block: 99 bd 1 0 0      (DW_OP_call4: <0x1bd>)
        <2d3>   DW_AT_byte_size   : 4
        <2d4>   DW_AT_sibling     : <0x2e2>
    
    In this type entry the DW_AT_string_length attribute references a
    second DW_TAG_formal_parameter that contains the string length.  The
    DW_AT_byte_size indicates that the length is a 4-byte value.
    
    This commit extends GDB's DWARF parsing for strings so that we can
    create dynamic types as well as static types, based on the attribute
    the DWARF contains.
    
    I then extend the dynamic type resolution code in gdbtypes.c to add
    support for resolving dynamic strings.
    
    gdb/ChangeLog:
    
            * dwarf2read.c (read_tag_string_type): Read the fields required to
            make a dynamic string, and possibly create a dynamic range for the
            string.
            (attr_to_dynamic_prop): Setup is_reference based on the type of
            attribute being processed.
            * gdbtypes.c (is_dynamic_type_internal): Handle TYPE_CODE_STRING.
            (resolve_dynamic_array): Rename to...
            (resolve_dynamic_array_or_string): ...this, update header comment,
            and accept TYPE_CODE_STRING.
            (resolve_dynamic_type_internal): Handle TYPE_CODE_STRING.
    
    gdb/testsuite/ChangeLog:
    
            * gdb.fortran/array-slices.exp: Add test for dynamic strings.
    
    Change-Id: I03f2d181b26156f48f27a03c8a59f9bd4d71ac17

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 98a3c6598d..1465c756ab 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2019-12-01  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* dwarf2read.c (read_tag_string_type): Read the fields required to
+	make a dynamic string, and possibly create a dynamic range for the
+	string.
+	(attr_to_dynamic_prop): Setup is_reference based on the type of
+	attribute being processed.
+	* gdbtypes.c (is_dynamic_type_internal): Handle TYPE_CODE_STRING.
+	(resolve_dynamic_array): Rename to...
+	(resolve_dynamic_array_or_string): ...this, update header comment,
+	and accept TYPE_CODE_STRING.
+	(resolve_dynamic_type_internal): Handle TYPE_CODE_STRING.
+
 2019-12-01  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* dwarf2read.c (dwarf2_per_cu_int_type): New function, takes most
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index cd114d0bf6..327837cc3c 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -17323,29 +17323,90 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct type *type, *range_type, *index_type, *char_type;
   struct attribute *attr;
-  unsigned int length;
+  struct dynamic_prop prop;
+  bool length_is_constant = true;
+  LONGEST length;
+
+  /* There are a couple of places where bit sizes might be made use of
+     when parsing a DW_TAG_string_type, however, no producer that we know
+     of make use of these.  Handling bit sizes that are a multiple of the
+     byte size is easy enough, but what about other bit sizes?  Lets deal
+     with that problem when we have to.  Warn about these attributes being
+     unsupported, then parse the type and ignore them like we always
+     have.  */
+  if (dwarf2_attr (die, DW_AT_bit_size, cu) != nullptr
+      || dwarf2_attr (die, DW_AT_string_length_bit_size, cu) != nullptr)
+    {
+      static bool warning_printed = false;
+      if (!warning_printed)
+	{
+	  warning (_("DW_AT_bit_size and DW_AT_string_length_bit_size not "
+		     "currently supported on DW_TAG_string_type."));
+	  warning_printed = true;
+	}
+    }
 
   attr = dwarf2_attr (die, DW_AT_string_length, cu);
-  if (attr != nullptr)
+  if (attr != nullptr && !attr_form_is_constant (attr))
+    {
+      /* The string length describes the location at which the length of
+	 the string can be found.  The size of the length field can be
+	 specified with one of the attributes below.  */
+      struct type *prop_type;
+      struct attribute *len
+	= dwarf2_attr (die, DW_AT_string_length_byte_size, cu);
+      if (len == nullptr)
+	len = dwarf2_attr (die, DW_AT_byte_size, cu);
+      if (len != nullptr && attr_form_is_constant (len))
+	{
+	  /* Pass 0 as the default as we know this attribute is constant
+	     and the default value will not be returned.  */
+	  LONGEST sz = dwarf2_get_attr_constant_value (len, 0);
+	  prop_type = dwarf2_per_cu_int_type (cu->per_cu, sz, true);
+	}
+      else
+	{
+	  /* If the size is not specified then we assume it is the size of
+	     an address on this target.  */
+	  prop_type = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, true);
+	}
+
+      /* Convert the attribute into a dynamic property.  */
+      if (!attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
+	length = 1;
+      else
+	length_is_constant = false;
+    }
+  else if (attr != nullptr)
+    {
+      /* This DW_AT_string_length just contains the length with no
+	 indirection.  There's no need to create a dynamic property in this
+	 case.  Pass 0 for the default value as we know it will not be
+	 returned in this case.  */
+      length = dwarf2_get_attr_constant_value (attr, 0);
+    }
+  else if ((attr = dwarf2_attr (die, DW_AT_byte_size, cu)) != nullptr)
     {
-      length = DW_UNSND (attr);
+      /* We don't currently support non-constant byte sizes for strings.  */
+      length = dwarf2_get_attr_constant_value (attr, 1);
     }
   else
     {
-      /* Check for the DW_AT_byte_size attribute.  */
-      attr = dwarf2_attr (die, DW_AT_byte_size, cu);
-      if (attr != nullptr)
-        {
-          length = DW_UNSND (attr);
-        }
-      else
-        {
-          length = 1;
-        }
+      /* Use 1 as a fallback length if we have nothing else.  */
+      length = 1;
     }
 
   index_type = objfile_type (objfile)->builtin_int;
-  range_type = create_static_range_type (NULL, index_type, 1, length);
+  if (length_is_constant)
+    range_type = create_static_range_type (NULL, index_type, 1, length);
+  else
+    {
+      struct dynamic_prop low_bound;
+
+      low_bound.kind = PROP_CONST;
+      low_bound.data.const_val = 1;
+      range_type = create_range_type (NULL, index_type, &low_bound, &prop, 0);
+    }
   char_type = language_string_char_type (cu->language_defn, gdbarch);
   type = create_string_type (NULL, char_type, range_type);
 
@@ -17806,7 +17867,15 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
       baton->locexpr.per_cu = cu->per_cu;
       baton->locexpr.size = DW_BLOCK (attr)->size;
       baton->locexpr.data = DW_BLOCK (attr)->data;
-      baton->locexpr.is_reference = false;
+      switch (attr->name)
+	{
+	case DW_AT_string_length:
+	  baton->locexpr.is_reference = true;
+	  break;
+	default:
+	  baton->locexpr.is_reference = false;
+	  break;
+	}
       prop->data.baton = baton;
       prop->kind = PROP_LOCEXPR;
       gdb_assert (prop->data.baton != NULL);
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index b1e03d1643..f10f65d0da 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1967,6 +1967,9 @@ is_dynamic_type_internal (struct type *type, int top_level)
 		|| is_dynamic_type_internal (TYPE_TARGET_TYPE (type), 0));
       }
 
+    case TYPE_CODE_STRING:
+      /* Strings are very much like an array of characters, and can be
+	 treated as one here.  */
     case TYPE_CODE_ARRAY:
       {
 	gdb_assert (TYPE_NFIELDS (type) == 1);
@@ -2088,13 +2091,13 @@ resolve_dynamic_range (struct type *dyn_range_type,
   return static_range_type;
 }
 
-/* Resolves dynamic bound values of an array type TYPE to static ones.
-   ADDR_STACK is a stack of struct property_addr_info to be used
-   if needed during the dynamic resolution.  */
+/* Resolves dynamic bound values of an array or string type TYPE to static
+   ones.  ADDR_STACK is a stack of struct property_addr_info to be used if
+   needed during the dynamic resolution.  */
 
 static struct type *
-resolve_dynamic_array (struct type *type,
-		       struct property_addr_info *addr_stack)
+resolve_dynamic_array_or_string (struct type *type,
+				 struct property_addr_info *addr_stack)
 {
   CORE_ADDR value;
   struct type *elt_type;
@@ -2103,7 +2106,10 @@ resolve_dynamic_array (struct type *type,
   struct dynamic_prop *prop;
   unsigned int bit_stride = 0;
 
-  gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
+  /* For dynamic type resolution strings can be treated like arrays of
+     characters.  */
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY
+	      || TYPE_CODE (type) == TYPE_CODE_STRING);
 
   type = copy_type (type);
 
@@ -2129,7 +2135,7 @@ resolve_dynamic_array (struct type *type,
   ary_dim = check_typedef (TYPE_TARGET_TYPE (elt_type));
 
   if (ary_dim != NULL && TYPE_CODE (ary_dim) == TYPE_CODE_ARRAY)
-    elt_type = resolve_dynamic_array (ary_dim, addr_stack);
+    elt_type = resolve_dynamic_array_or_string (ary_dim, addr_stack);
   else
     elt_type = TYPE_TARGET_TYPE (type);
 
@@ -2332,8 +2338,11 @@ resolve_dynamic_type_internal (struct type *type,
 	    break;
 	  }
 
+	case TYPE_CODE_STRING:
+	  /* Strings are very much like an array of characters, and can be
+	     treated as one here.  */
 	case TYPE_CODE_ARRAY:
-	  resolved_type = resolve_dynamic_array (type, addr_stack);
+	  resolved_type = resolve_dynamic_array_or_string (type, addr_stack);
 	  break;
 
 	case TYPE_CODE_RANGE:
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index f3bffa5dbe..a4d2556c90 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2019-12-01  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* gdb.fortran/array-slices.exp: Add test for dynamic strings.
+
 2019-12-01  Richard Bunt  <richard.bunt@arm.com>
 	    Andrew Burgess  <andrew.burgess@embecosm.com>
 
diff --git a/gdb/testsuite/gdb.fortran/array-slices.exp b/gdb/testsuite/gdb.fortran/array-slices.exp
index db07ace0b3..7a7baf76d2 100644
--- a/gdb/testsuite/gdb.fortran/array-slices.exp
+++ b/gdb/testsuite/gdb.fortran/array-slices.exp
@@ -46,12 +46,21 @@ set array_contents \
 	 " = \\(\\( -26, -25, -24, -23, -22, -21\\) \\( -19, -18, -17, -16, -15, -14\\) \\( -12, -11, -10, -9, -8, -7\\) \\)" \
 	 " = \\(\\( -26, -24, -22, -20, -18\\) \\( -5, -3, -1, 1, 3\\) \\( 16, 18, 20, 22, 24\\) \\( 37, 39, 41, 43, 45\\) \\)" ]
 
+set message_strings \
+    [list \
+	 " = 'array'" \
+	 " = 'array \\(1:5,1:5\\)'" \
+	 " = 'array \\(1:10:2,1:10:2\\)'" \
+	 " = 'array \\(1:10:3,1:10:2\\)'" \
+	 " = 'array \\(1:10:5,1:10:3\\)'" ]
+
 set i 0
-foreach result $array_contents {
+foreach result $array_contents msg $message_strings {
     incr i
     with_test_prefix "test $i" {
 	gdb_continue_to_breakpoint "show"
 	gdb_test "p array" $result
+	gdb_test "p message" "$msg"
     }
 }
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-12-02 13:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-02  0:49 [binutils-gdb] gdb: Dynamic string length support gdb-buildbot
2019-12-02  0:49 ` Failures on Ubuntu-Aarch64-native-extended-gdbserver-m64, branch master gdb-buildbot
2019-12-02 12:31 ` Failures on Fedora-x86_64-m32, " gdb-buildbot
2019-12-02 12:34 ` Failures on Fedora-x86_64-m64, " gdb-buildbot
2019-12-02 12:50 ` Failures on Fedora-x86_64-native-extended-gdbserver-m32, " gdb-buildbot
2019-12-02 12:57 ` *** COMPILATION FAILED *** Failures on Fedora-x86_64-w64-mingw32, branch master *** BREAKAGE *** gdb-buildbot
2019-12-02 13:05 ` Failures on Fedora-x86_64-native-gdbserver-m32, branch master gdb-buildbot
2019-12-02 13:08 ` Failures on Fedora-x86_64-native-gdbserver-m64, " gdb-buildbot
2019-12-02 13:09 ` Failures on Fedora-x86_64-native-extended-gdbserver-m64, " gdb-buildbot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).