public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA] Ensure GDB printf command can print convenience var strings without a target.
@ 2019-06-10 21:16 Philippe Waroquiers
  2019-06-11  2:29 ` Eli Zaretskii
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Philippe Waroquiers @ 2019-06-10 21:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

Without this patch, GDB printf command calls malloc on the target,
writes the convenience var content to the target,
re-reads the content from the target, and then locally printf the string.

This implies inferior calls, and does not work when there is no inferior,
or when the inferior is a core dump.

With this patch, printf command can printf string convenience variables
without inferior function calls.
Ada string convenience variables can also be printed.

gdb/ChangeLog

2019-06-10  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* NEWS: Mention that GDB printf and eval commands can now print
	C-style and Ada-style convenience var strings without
	calling the inferior.
	* printcmd.c (printf_c_string): Locally print GDB internal var
	instead of transiting via the inferior.
	(printf_wide_c_string): Likewise.

2019-06-10  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/printcmds.exp: Test printing C strings and
	C wide strings convenience var without transiting via the inferior.
---
 gdb/NEWS                             |   7 ++
 gdb/printcmd.c                       | 143 +++++++++++++++++----------
 gdb/testsuite/gdb.base/printcmds.exp |  39 ++++++++
 3 files changed, 136 insertions(+), 53 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 9e1462b6bf..9d6a2de661 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -98,6 +98,13 @@ apropos [-v] REGEXP
   of matching commands and to use the highlight style to mark
   the documentation parts matching REGEXP.
 
+printf
+eval
+  The GDB printf and eval commands can now print C-style and Ada-style
+  convenience variables without calling functions in the program.
+  This allows to do formatted printing of strings without having
+  an inferior, or when debugging a core dump.
+
 show style
   The "show style" and its subcommands are now styling
   a style name in their output using its own style, to help
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 9e84594fe6..d7b8b9a1c1 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -23,6 +23,7 @@
 #include "gdbtypes.h"
 #include "value.h"
 #include "language.h"
+#include "c-lang.h"
 #include "expression.h"
 #include "gdbcore.h"
 #include "gdbcmd.h"
@@ -2200,91 +2201,127 @@ print_variable_and_value (const char *name, struct symbol *var,
 
 /* Subroutine of ui_printf to simplify it.
    Print VALUE to STREAM using FORMAT.
-   VALUE is a C-style string on the target.  */
+   VALUE is a C-style string on the target or a C-style string
+   in a GDB internal variable.  */
 
 static void
 printf_c_string (struct ui_file *stream, const char *format,
 		 struct value *value)
 {
-  gdb_byte *str;
-  CORE_ADDR tem;
-  int j;
+  const gdb_byte *str;
 
-  tem = value_as_address (value);
-  if (tem == 0)
+  if (VALUE_LVAL (value) == lval_internalvar
+      && c_is_string_type_p (value_type (value)))
     {
-      DIAGNOSTIC_PUSH
-      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-      fprintf_filtered (stream, format, "(null)");
-      DIAGNOSTIC_POP
-      return;
-    }
+      gdb_byte *tem_str;
+      size_t len  = TYPE_LENGTH (value_type (value));
 
-  /* This is a %s argument.  Find the length of the string.  */
-  for (j = 0;; j++)
+      /* Copy the internal var value to tem_str and append a terminating null
+	 character.  This protects against corrupted C-style strings that lacks
+	 the terminating null char.  It also allows Ada style strings (not not
+	 null terminated) to be printed without problems.  */
+      tem_str = (gdb_byte *) alloca (len + 1);
+      memcpy (tem_str, value_contents (value), len);
+      tem_str [len] = 0;
+      str = tem_str;
+    }
+  else
     {
-      gdb_byte c;
+      int len;
+      CORE_ADDR tem;
+      gdb_byte *tem_str;
 
-      QUIT;
-      read_memory (tem + j, &c, 1);
-      if (c == 0)
-	break;
-    }
+      tem = value_as_address (value);
+      if (tem == 0)
+	{
+	  DIAGNOSTIC_PUSH
+	    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+	    fprintf_filtered (stream, format, "(null)");
+	  DIAGNOSTIC_POP
+	    return;
+	}
 
-  /* Copy the string contents into a string inside GDB.  */
-  str = (gdb_byte *) alloca (j + 1);
-  if (j != 0)
-    read_memory (tem, str, j);
-  str[j] = 0;
+      /* This is a %s argument.  Find the length of the string.  */
+      for (len = 0;; len++)
+	{
+	  gdb_byte c;
+
+	  QUIT;
+	  read_memory (tem + len, &c, 1);
+	  if (c == 0)
+	    break;
+	}
+
+      /* Copy the string contents into a string inside GDB.  */
+      tem_str = (gdb_byte *) alloca (len + 1);
+      if (len != 0)
+	read_memory (tem, tem_str, len);
+      tem_str[len] = 0;
+      str = tem_str;
+    }
 
   DIAGNOSTIC_PUSH
-  DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-  fprintf_filtered (stream, format, (char *) str);
+    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+    fprintf_filtered (stream, format, (char *) str);
   DIAGNOSTIC_POP
-}
+    }
 
 /* Subroutine of ui_printf to simplify it.
    Print VALUE to STREAM using FORMAT.
-   VALUE is a wide C-style string on the target.  */
+   VALUE is a wide C-style string on the target or a wide C-style string
+   in a GDB internal variable.  */
 
 static void
 printf_wide_c_string (struct ui_file *stream, const char *format,
 		      struct value *value)
 {
-  gdb_byte *str;
-  CORE_ADDR tem;
+  const gdb_byte *str;
   int j;
   struct gdbarch *gdbarch = get_type_arch (value_type (value));
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct type *wctype = lookup_typename (current_language, gdbarch,
 					 "wchar_t", NULL, 0);
   int wcwidth = TYPE_LENGTH (wctype);
-  gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
 
-  tem = value_as_address (value);
-  if (tem == 0)
+  if (VALUE_LVAL (value) == lval_internalvar
+      && c_is_string_type_p (value_type (value)))
     {
-      DIAGNOSTIC_PUSH
-      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-      fprintf_filtered (stream, format, "(null)");
-      DIAGNOSTIC_POP
-      return;
+      str = value_contents (value);
+      j = TYPE_LENGTH (value_type (value));
     }
-
-  /* This is a %s argument.  Find the length of the string.  */
-  for (j = 0;; j += wcwidth)
+  else
     {
-      QUIT;
-      read_memory (tem + j, buf, wcwidth);
-      if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
-	break;
-    }
+      gdb_byte *tem_str;
+      CORE_ADDR tem;
+      gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
 
-  /* Copy the string contents into a string inside GDB.  */
-  str = (gdb_byte *) alloca (j + wcwidth);
-  if (j != 0)
-    read_memory (tem, str, j);
-  memset (&str[j], 0, wcwidth);
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+      tem = value_as_address (value);
+      if (tem == 0)
+	{
+	  DIAGNOSTIC_PUSH
+	    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+	    fprintf_filtered (stream, format, "(null)");
+	  DIAGNOSTIC_POP
+	    return;
+	}
+
+      /* This is a %s argument.  Find the length of the string.  */
+      for (j = 0;; j += wcwidth)
+	{
+	  QUIT;
+	  read_memory (tem + j, buf, wcwidth);
+	  if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
+	    break;
+	}
+
+      /* Copy the string contents into a string inside GDB.  */
+      tem_str = (gdb_byte *) alloca (j + wcwidth);
+      if (j != 0)
+	read_memory (tem, tem_str, j);
+      memset (&tem_str[j], 0, wcwidth);
+      str = tem_str;
+    }
 
   auto_obstack output;
 
diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
index f2d6ee229d..3b6562426e 100644
--- a/gdb/testsuite/gdb.base/printcmds.exp
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -932,6 +932,32 @@ proc test_repeat_bytes {} {
     }
 }
 
+proc test_printf_convenience_var {prefix do_wstring} {
+
+    with_test_prefix $prefix {
+	gdb_test_no_output "set var \$cstr = \"abcde\"" "set \$cstr, conv var"
+	gdb_test "printf \"cstr val = %s\\n\", \$cstr" "cstr val = abcde" \
+	    "printf \$cstr, conv var"
+	gdb_test_no_output "set var \$abcde = \"ABCDE\"" "set \$abcde, conv var"
+	gdb_test "eval \"print \$%s\\n\", \$cstr" "= \"ABCDE\"" \
+	    "indirect print abcde"
+	gdb_test "set language ada" ".*" "set language ada, conv var"
+	gdb_test_no_output "set var \$astr := \"fghij\"" "set \$astr, conv var"
+	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
+	    "printf \$astr, conv var"
+	gdb_test "set language auto" ".*" "set language auto, conv var"
+	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
+	    "printf \$astr, conv var, auto language"
+	if ($do_wstring) {
+	    gdb_test_no_output "set var \$wstr = L\"facile\"" \
+		"set \$wstr, conv var"
+	    gdb_test "printf \"wstr val = %ls\\n\", \$wstr" \
+		"wstr val = facile" "printf \$wstr, conv var"
+	}
+    }
+}
+
+
 # Start with a fresh gdb.
 
 gdb_exit
@@ -948,6 +974,11 @@ gdb_test "ptype \"abc\"" " = char \\\[4\\\]"
 gdb_test "print \$cvar = \"abc\"" " = \"abc\""
 gdb_test "print sizeof (\$cvar)" " = 4"
 
+# Similarly, printf of convenience var should work without a target.
+# At this point, we cannot create wide strings convenience var, as the
+# type wchar_t is not yet known, so skip the wide string tests.
+test_printf_convenience_var "no target" 0
+
 # GDB used to complete the explicit location options even when
 # printing expressions.
 gdb_test_no_output "complete p -function"
@@ -977,6 +1008,14 @@ if ![runto_main] then {
     return 0
 }
 
+# With a target, printf convenience var should of course work.
+test_printf_convenience_var "with target" 1
+
+# But it should also work when inferior function calls are forbidden.
+gdb_test_no_output "set may-call-functions off"
+test_printf_convenience_var "with target, may-call-functions off" 1
+gdb_test_no_output "set may-call-functions on"
+
 test_integer_literals_accepted
 test_integer_literals_rejected
 test_float_accepted
-- 
2.20.1

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

* Re: [RFA] Ensure GDB printf command can print convenience var strings without a target.
  2019-06-10 21:16 [RFA] Ensure GDB printf command can print convenience var strings without a target Philippe Waroquiers
@ 2019-06-11  2:29 ` Eli Zaretskii
  2019-07-05 20:01 ` PING " Philippe Waroquiers
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 18+ messages in thread
From: Eli Zaretskii @ 2019-06-11  2:29 UTC (permalink / raw)
  To: Philippe Waroquiers; +Cc: gdb-patches

> From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
> Cc: Philippe Waroquiers <philippe.waroquiers@skynet.be>
> Date: Mon, 10 Jun 2019 23:16:22 +0200
> 
> Without this patch, GDB printf command calls malloc on the target,
> writes the convenience var content to the target,
> re-reads the content from the target, and then locally printf the string.
> 
> This implies inferior calls, and does not work when there is no inferior,
> or when the inferior is a core dump.
> 
> With this patch, printf command can printf string convenience variables
> without inferior function calls.
> Ada string convenience variables can also be printed.
> 
> gdb/ChangeLog
> 
> 2019-06-10  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* NEWS: Mention that GDB printf and eval commands can now print
> 	C-style and Ada-style convenience var strings without
> 	calling the inferior.
> 	* printcmd.c (printf_c_string): Locally print GDB internal var
> 	instead of transiting via the inferior.
> 	(printf_wide_c_string): Likewise.
> 
> 2019-06-10  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* gdb.base/printcmds.exp: Test printing C strings and
> 	C wide strings convenience var without transiting via the inferior.
> ---
>  gdb/NEWS                             |   7 ++
>  gdb/printcmd.c                       | 143 +++++++++++++++++----------
>  gdb/testsuite/gdb.base/printcmds.exp |  39 ++++++++
>  3 files changed, 136 insertions(+), 53 deletions(-)

The NEWS part is OK, thanks.

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

* PING Re: [RFA] Ensure GDB printf command can print convenience var strings without a target.
  2019-06-10 21:16 [RFA] Ensure GDB printf command can print convenience var strings without a target Philippe Waroquiers
  2019-06-11  2:29 ` Eli Zaretskii
@ 2019-07-05 20:01 ` Philippe Waroquiers
  2019-07-08 18:13 ` Pedro Alves
  2020-03-02  2:46 ` [PATCH] Fix printf of a convenience variable holding an inferior address Sergio Durigan Junior
  3 siblings, 0 replies; 18+ messages in thread
From: Philippe Waroquiers @ 2019-07-05 20:01 UTC (permalink / raw)
  To: gdb-patches

Ping ?

Thanks

Philippe

On Mon, 2019-06-10 at 23:16 +0200, Philippe Waroquiers wrote:
> Without this patch, GDB printf command calls malloc on the target,
> writes the convenience var content to the target,
> re-reads the content from the target, and then locally printf the string.
> 
> This implies inferior calls, and does not work when there is no inferior,
> or when the inferior is a core dump.
> 
> With this patch, printf command can printf string convenience variables
> without inferior function calls.
> Ada string convenience variables can also be printed.
> 
> gdb/ChangeLog
> 
> 2019-06-10  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* NEWS: Mention that GDB printf and eval commands can now print
> 	C-style and Ada-style convenience var strings without
> 	calling the inferior.
> 	* printcmd.c (printf_c_string): Locally print GDB internal var
> 	instead of transiting via the inferior.
> 	(printf_wide_c_string): Likewise.
> 
> 2019-06-10  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* gdb.base/printcmds.exp: Test printing C strings and
> 	C wide strings convenience var without transiting via the inferior.
> ---
>  gdb/NEWS                             |   7 ++
>  gdb/printcmd.c                       | 143 +++++++++++++++++----------
>  gdb/testsuite/gdb.base/printcmds.exp |  39 ++++++++
>  3 files changed, 136 insertions(+), 53 deletions(-)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 9e1462b6bf..9d6a2de661 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -98,6 +98,13 @@ apropos [-v] REGEXP
>    of matching commands and to use the highlight style to mark
>    the documentation parts matching REGEXP.
>  
> +printf
> +eval
> +  The GDB printf and eval commands can now print C-style and Ada-style
> +  convenience variables without calling functions in the program.
> +  This allows to do formatted printing of strings without having
> +  an inferior, or when debugging a core dump.
> +
>  show style
>    The "show style" and its subcommands are now styling
>    a style name in their output using its own style, to help
> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index 9e84594fe6..d7b8b9a1c1 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -23,6 +23,7 @@
>  #include "gdbtypes.h"
>  #include "value.h"
>  #include "language.h"
> +#include "c-lang.h"
>  #include "expression.h"
>  #include "gdbcore.h"
>  #include "gdbcmd.h"
> @@ -2200,91 +2201,127 @@ print_variable_and_value (const char *name, struct symbol *var,
>  
>  /* Subroutine of ui_printf to simplify it.
>     Print VALUE to STREAM using FORMAT.
> -   VALUE is a C-style string on the target.  */
> +   VALUE is a C-style string on the target or a C-style string
> +   in a GDB internal variable.  */
>  
>  static void
>  printf_c_string (struct ui_file *stream, const char *format,
>  		 struct value *value)
>  {
> -  gdb_byte *str;
> -  CORE_ADDR tem;
> -  int j;
> +  const gdb_byte *str;
>  
> -  tem = value_as_address (value);
> -  if (tem == 0)
> +  if (VALUE_LVAL (value) == lval_internalvar
> +      && c_is_string_type_p (value_type (value)))
>      {
> -      DIAGNOSTIC_PUSH
> -      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> -      fprintf_filtered (stream, format, "(null)");
> -      DIAGNOSTIC_POP
> -      return;
> -    }
> +      gdb_byte *tem_str;
> +      size_t len  = TYPE_LENGTH (value_type (value));
>  
> -  /* This is a %s argument.  Find the length of the string.  */
> -  for (j = 0;; j++)
> +      /* Copy the internal var value to tem_str and append a terminating null
> +	 character.  This protects against corrupted C-style strings that lacks
> +	 the terminating null char.  It also allows Ada style strings (not not
> +	 null terminated) to be printed without problems.  */
> +      tem_str = (gdb_byte *) alloca (len + 1);
> +      memcpy (tem_str, value_contents (value), len);
> +      tem_str [len] = 0;
> +      str = tem_str;
> +    }
> +  else
>      {
> -      gdb_byte c;
> +      int len;
> +      CORE_ADDR tem;
> +      gdb_byte *tem_str;
>  
> -      QUIT;
> -      read_memory (tem + j, &c, 1);
> -      if (c == 0)
> -	break;
> -    }
> +      tem = value_as_address (value);
> +      if (tem == 0)
> +	{
> +	  DIAGNOSTIC_PUSH
> +	    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> +	    fprintf_filtered (stream, format, "(null)");
> +	  DIAGNOSTIC_POP
> +	    return;
> +	}
>  
> -  /* Copy the string contents into a string inside GDB.  */
> -  str = (gdb_byte *) alloca (j + 1);
> -  if (j != 0)
> -    read_memory (tem, str, j);
> -  str[j] = 0;
> +      /* This is a %s argument.  Find the length of the string.  */
> +      for (len = 0;; len++)
> +	{
> +	  gdb_byte c;
> +
> +	  QUIT;
> +	  read_memory (tem + len, &c, 1);
> +	  if (c == 0)
> +	    break;
> +	}
> +
> +      /* Copy the string contents into a string inside GDB.  */
> +      tem_str = (gdb_byte *) alloca (len + 1);
> +      if (len != 0)
> +	read_memory (tem, tem_str, len);
> +      tem_str[len] = 0;
> +      str = tem_str;
> +    }
>  
>    DIAGNOSTIC_PUSH
> -  DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> -  fprintf_filtered (stream, format, (char *) str);
> +    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> +    fprintf_filtered (stream, format, (char *) str);
>    DIAGNOSTIC_POP
> -}
> +    }
>  
>  /* Subroutine of ui_printf to simplify it.
>     Print VALUE to STREAM using FORMAT.
> -   VALUE is a wide C-style string on the target.  */
> +   VALUE is a wide C-style string on the target or a wide C-style string
> +   in a GDB internal variable.  */
>  
>  static void
>  printf_wide_c_string (struct ui_file *stream, const char *format,
>  		      struct value *value)
>  {
> -  gdb_byte *str;
> -  CORE_ADDR tem;
> +  const gdb_byte *str;
>    int j;
>    struct gdbarch *gdbarch = get_type_arch (value_type (value));
> -  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>    struct type *wctype = lookup_typename (current_language, gdbarch,
>  					 "wchar_t", NULL, 0);
>    int wcwidth = TYPE_LENGTH (wctype);
> -  gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
>  
> -  tem = value_as_address (value);
> -  if (tem == 0)
> +  if (VALUE_LVAL (value) == lval_internalvar
> +      && c_is_string_type_p (value_type (value)))
>      {
> -      DIAGNOSTIC_PUSH
> -      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> -      fprintf_filtered (stream, format, "(null)");
> -      DIAGNOSTIC_POP
> -      return;
> +      str = value_contents (value);
> +      j = TYPE_LENGTH (value_type (value));
>      }
> -
> -  /* This is a %s argument.  Find the length of the string.  */
> -  for (j = 0;; j += wcwidth)
> +  else
>      {
> -      QUIT;
> -      read_memory (tem + j, buf, wcwidth);
> -      if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
> -	break;
> -    }
> +      gdb_byte *tem_str;
> +      CORE_ADDR tem;
> +      gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
>  
> -  /* Copy the string contents into a string inside GDB.  */
> -  str = (gdb_byte *) alloca (j + wcwidth);
> -  if (j != 0)
> -    read_memory (tem, str, j);
> -  memset (&str[j], 0, wcwidth);
> +      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +
> +      tem = value_as_address (value);
> +      if (tem == 0)
> +	{
> +	  DIAGNOSTIC_PUSH
> +	    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> +	    fprintf_filtered (stream, format, "(null)");
> +	  DIAGNOSTIC_POP
> +	    return;
> +	}
> +
> +      /* This is a %s argument.  Find the length of the string.  */
> +      for (j = 0;; j += wcwidth)
> +	{
> +	  QUIT;
> +	  read_memory (tem + j, buf, wcwidth);
> +	  if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
> +	    break;
> +	}
> +
> +      /* Copy the string contents into a string inside GDB.  */
> +      tem_str = (gdb_byte *) alloca (j + wcwidth);
> +      if (j != 0)
> +	read_memory (tem, tem_str, j);
> +      memset (&tem_str[j], 0, wcwidth);
> +      str = tem_str;
> +    }
>  
>    auto_obstack output;
>  
> diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
> index f2d6ee229d..3b6562426e 100644
> --- a/gdb/testsuite/gdb.base/printcmds.exp
> +++ b/gdb/testsuite/gdb.base/printcmds.exp
> @@ -932,6 +932,32 @@ proc test_repeat_bytes {} {
>      }
>  }
>  
> +proc test_printf_convenience_var {prefix do_wstring} {
> +
> +    with_test_prefix $prefix {
> +	gdb_test_no_output "set var \$cstr = \"abcde\"" "set \$cstr, conv var"
> +	gdb_test "printf \"cstr val = %s\\n\", \$cstr" "cstr val = abcde" \
> +	    "printf \$cstr, conv var"
> +	gdb_test_no_output "set var \$abcde = \"ABCDE\"" "set \$abcde, conv var"
> +	gdb_test "eval \"print \$%s\\n\", \$cstr" "= \"ABCDE\"" \
> +	    "indirect print abcde"
> +	gdb_test "set language ada" ".*" "set language ada, conv var"
> +	gdb_test_no_output "set var \$astr := \"fghij\"" "set \$astr, conv var"
> +	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
> +	    "printf \$astr, conv var"
> +	gdb_test "set language auto" ".*" "set language auto, conv var"
> +	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
> +	    "printf \$astr, conv var, auto language"
> +	if ($do_wstring) {
> +	    gdb_test_no_output "set var \$wstr = L\"facile\"" \
> +		"set \$wstr, conv var"
> +	    gdb_test "printf \"wstr val = %ls\\n\", \$wstr" \
> +		"wstr val = facile" "printf \$wstr, conv var"
> +	}
> +    }
> +}
> +
> +
>  # Start with a fresh gdb.
>  
>  gdb_exit
> @@ -948,6 +974,11 @@ gdb_test "ptype \"abc\"" " = char \\\[4\\\]"
>  gdb_test "print \$cvar = \"abc\"" " = \"abc\""
>  gdb_test "print sizeof (\$cvar)" " = 4"
>  
> +# Similarly, printf of convenience var should work without a target.
> +# At this point, we cannot create wide strings convenience var, as the
> +# type wchar_t is not yet known, so skip the wide string tests.
> +test_printf_convenience_var "no target" 0
> +
>  # GDB used to complete the explicit location options even when
>  # printing expressions.
>  gdb_test_no_output "complete p -function"
> @@ -977,6 +1008,14 @@ if ![runto_main] then {
>      return 0
>  }
>  
> +# With a target, printf convenience var should of course work.
> +test_printf_convenience_var "with target" 1
> +
> +# But it should also work when inferior function calls are forbidden.
> +gdb_test_no_output "set may-call-functions off"
> +test_printf_convenience_var "with target, may-call-functions off" 1
> +gdb_test_no_output "set may-call-functions on"
> +
>  test_integer_literals_accepted
>  test_integer_literals_rejected
>  test_float_accepted

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

* Re: [RFA] Ensure GDB printf command can print convenience var strings without a target.
  2019-06-10 21:16 [RFA] Ensure GDB printf command can print convenience var strings without a target Philippe Waroquiers
  2019-06-11  2:29 ` Eli Zaretskii
  2019-07-05 20:01 ` PING " Philippe Waroquiers
@ 2019-07-08 18:13 ` Pedro Alves
  2019-07-08 22:41   ` Philippe Waroquiers
  2020-03-02  2:46 ` [PATCH] Fix printf of a convenience variable holding an inferior address Sergio Durigan Junior
  3 siblings, 1 reply; 18+ messages in thread
From: Pedro Alves @ 2019-07-08 18:13 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches

Looks fine to me, with the nits below fixed.

On 6/10/19 10:16 PM, Philippe Waroquiers wrote:
> Without this patch, GDB printf command calls malloc on the target,
> writes the convenience var content to the target,
> re-reads the content from the target, and then locally printf the string.
> 
> This implies inferior calls, and does not work when there is no inferior,
> or when the inferior is a core dump.
> 
> With this patch, printf command can printf string convenience variables
> without inferior function calls.
> Ada string convenience variables can also be printed.
> 
> gdb/ChangeLog
> 
> 2019-06-10  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* NEWS: Mention that GDB printf and eval commands can now print
> 	C-style and Ada-style convenience var strings without
> 	calling the inferior.
> 	* printcmd.c (printf_c_string): Locally print GDB internal var
> 	instead of transiting via the inferior.
> 	(printf_wide_c_string): Likewise.
> 
> 2019-06-10  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* gdb.base/printcmds.exp: Test printing C strings and
> 	C wide strings convenience var without transiting via the inferior.
> ---
>  gdb/NEWS                             |   7 ++
>  gdb/printcmd.c                       | 143 +++++++++++++++++----------
>  gdb/testsuite/gdb.base/printcmds.exp |  39 ++++++++
>  3 files changed, 136 insertions(+), 53 deletions(-)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 9e1462b6bf..9d6a2de661 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -98,6 +98,13 @@ apropos [-v] REGEXP
>    of matching commands and to use the highlight style to mark
>    the documentation parts matching REGEXP.
>  
> +printf
> +eval
> +  The GDB printf and eval commands can now print C-style and Ada-style
> +  convenience variables without calling functions in the program.
> +  This allows to do formatted printing of strings without having
> +  an inferior, or when debugging a core dump.

Better say without having a _running_ inferior, since there's
always an inferior.

> +
>  show style
>    The "show style" and its subcommands are now styling
>    a style name in their output using its own style, to help
> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index 9e84594fe6..d7b8b9a1c1 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -23,6 +23,7 @@
>  #include "gdbtypes.h"
>  #include "value.h"
>  #include "language.h"
> +#include "c-lang.h"
>  #include "expression.h"
>  #include "gdbcore.h"
>  #include "gdbcmd.h"
> @@ -2200,91 +2201,127 @@ print_variable_and_value (const char *name, struct symbol *var,
>  
>  /* Subroutine of ui_printf to simplify it.
>     Print VALUE to STREAM using FORMAT.
> -   VALUE is a C-style string on the target.  */
> +   VALUE is a C-style string on the target or a C-style string
> +   in a GDB internal variable.  */

You could avoid the repetition:

   VALUE is a C-style string either on the target or in
   a GDB internal variable.  */

>  
>  static void
>  printf_c_string (struct ui_file *stream, const char *format,
>  		 struct value *value)
>  {
> -  gdb_byte *str;
> -  CORE_ADDR tem;
> -  int j;
> +  const gdb_byte *str;
>  
> -  tem = value_as_address (value);
> -  if (tem == 0)
> +  if (VALUE_LVAL (value) == lval_internalvar
> +      && c_is_string_type_p (value_type (value)))
>      {
> -      DIAGNOSTIC_PUSH
> -      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> -      fprintf_filtered (stream, format, "(null)");
> -      DIAGNOSTIC_POP
> -      return;
> -    }
> +      gdb_byte *tem_str;

You can declare tem_str at the point of initialization.

> +      size_t len  = TYPE_LENGTH (value_type (value));

Spurious double space after len.

>  
> -  /* This is a %s argument.  Find the length of the string.  */
> -  for (j = 0;; j++)
> +      /* Copy the internal var value to tem_str and append a terminating null

TEM_STR

> +	 character.  This protects against corrupted C-style strings that lacks

"strings that lack"

> +	 the terminating null char.  It also allows Ada style strings (not not

"Ada style strings" -> "Ada-style strings"

"not not" -> "not".

> +	 null terminated) to be printed without problems.  */
> +      tem_str = (gdb_byte *) alloca (len + 1);
> +      memcpy (tem_str, value_contents (value), len);
> +      tem_str [len] = 0;
> +      str = tem_str;
> +    }
> +  else
>      {
> -      gdb_byte c;
> +      int len;
> +      CORE_ADDR tem;
> +      gdb_byte *tem_str;

Ditto.


>  
> -      QUIT;
> -      read_memory (tem + j, &c, 1);
> -      if (c == 0)
> -	break;
> -    }
> +      tem = value_as_address (value);
> +      if (tem == 0)
> +	{
> +	  DIAGNOSTIC_PUSH
> +	    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> +	    fprintf_filtered (stream, format, "(null)");
> +	  DIAGNOSTIC_POP

Please align all these on the same column, like it was before.

> +	    return;
> +	}
>  
> -  /* Copy the string contents into a string inside GDB.  */
> -  str = (gdb_byte *) alloca (j + 1);
> -  if (j != 0)
> -    read_memory (tem, str, j);
> -  str[j] = 0;
> +      /* This is a %s argument.  Find the length of the string.  */
> +      for (len = 0;; len++)
> +	{
> +	  gdb_byte c;
> +
> +	  QUIT;
> +	  read_memory (tem + len, &c, 1);
> +	  if (c == 0)
> +	    break;
> +	}
> +
> +      /* Copy the string contents into a string inside GDB.  */
> +      tem_str = (gdb_byte *) alloca (len + 1);
> +      if (len != 0)
> +	read_memory (tem, tem_str, len);
> +      tem_str[len] = 0;
> +      str = tem_str;

I notice this renamed "j" -> "len", but the wide version
did not get the same treatment.

> +    }
>  
>    DIAGNOSTIC_PUSH
> -  DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> -  fprintf_filtered (stream, format, (char *) str);
> +    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> +    fprintf_filtered (stream, format, (char *) str);
>    DIAGNOSTIC_POP

Ditto.

> -}
> +    }
>  
>  /* Subroutine of ui_printf to simplify it.
>     Print VALUE to STREAM using FORMAT.
> -   VALUE is a wide C-style string on the target.  */
> +   VALUE is a wide C-style string on the target or a wide C-style string
> +   in a GDB internal variable.  */

Same comments as in the non-wide version apply.

>  
>  static void
>  printf_wide_c_string (struct ui_file *stream, const char *format,
>  		      struct value *value)
>  {
> -  gdb_byte *str;
> -  CORE_ADDR tem;
> +  const gdb_byte *str;
>    int j;
>    struct gdbarch *gdbarch = get_type_arch (value_type (value));
> -  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>    struct type *wctype = lookup_typename (current_language, gdbarch,
>  					 "wchar_t", NULL, 0);
>    int wcwidth = TYPE_LENGTH (wctype);
> -  gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
>  
> -  tem = value_as_address (value);
> -  if (tem == 0)
> +  if (VALUE_LVAL (value) == lval_internalvar
> +      && c_is_string_type_p (value_type (value)))
>      {
> -      DIAGNOSTIC_PUSH
> -      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> -      fprintf_filtered (stream, format, "(null)");
> -      DIAGNOSTIC_POP
> -      return;
> +      str = value_contents (value);
> +      j = TYPE_LENGTH (value_type (value));
>      }
> -
> -  /* This is a %s argument.  Find the length of the string.  */
> -  for (j = 0;; j += wcwidth)
> +  else
>      {
> -      QUIT;
> -      read_memory (tem + j, buf, wcwidth);
> -      if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
> -	break;
> -    }
> +      gdb_byte *tem_str;
> +      CORE_ADDR tem;
> +      gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
>  
> -  /* Copy the string contents into a string inside GDB.  */
> -  str = (gdb_byte *) alloca (j + wcwidth);
> -  if (j != 0)
> -    read_memory (tem, str, j);
> -  memset (&str[j], 0, wcwidth);
> +      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);

You could move this after the following if block, since byte_order
won't be needed until then.

> +
> +      tem = value_as_address (value);
> +      if (tem == 0)
> +	{
> +	  DIAGNOSTIC_PUSH
> +	    DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> +	    fprintf_filtered (stream, format, "(null)");
> +	  DIAGNOSTIC_POP
> +	    return;
> +	}
> +
> +      /* This is a %s argument.  Find the length of the string.  */
> +      for (j = 0;; j += wcwidth)
> +	{
> +	  QUIT;
> +	  read_memory (tem + j, buf, wcwidth);
> +	  if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
> +	    break;
> +	}
> +
> +      /* Copy the string contents into a string inside GDB.  */
> +      tem_str = (gdb_byte *) alloca (j + wcwidth);
> +      if (j != 0)
> +	read_memory (tem, tem_str, j);
> +      memset (&tem_str[j], 0, wcwidth);
> +      str = tem_str;
> +    }
>  
>    auto_obstack output;
>  
> diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
> index f2d6ee229d..3b6562426e 100644
> --- a/gdb/testsuite/gdb.base/printcmds.exp
> +++ b/gdb/testsuite/gdb.base/printcmds.exp
> @@ -932,6 +932,32 @@ proc test_repeat_bytes {} {
>      }
>  }
>  
> +proc test_printf_convenience_var {prefix do_wstring} {

Needs an intro comment.

> +
> +    with_test_prefix $prefix {
> +	gdb_test_no_output "set var \$cstr = \"abcde\"" "set \$cstr, conv var"
> +	gdb_test "printf \"cstr val = %s\\n\", \$cstr" "cstr val = abcde" \
> +	    "printf \$cstr, conv var"
> +	gdb_test_no_output "set var \$abcde = \"ABCDE\"" "set \$abcde, conv var"
> +	gdb_test "eval \"print \$%s\\n\", \$cstr" "= \"ABCDE\"" \
> +	    "indirect print abcde"

Missing ", conv var" ?  But see below.

> +	gdb_test "set language ada" ".*" "set language ada, conv var"

gdb_test_no_output ?

> +	gdb_test_no_output "set var \$astr := \"fghij\"" "set \$astr, conv var"
> +	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
> +	    "printf \$astr, conv var"
> +	gdb_test "set language auto" ".*" "set language auto, conv var"

gdb_test_no_output ?


> +	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
> +	    "printf \$astr, conv var, auto language"
> +	if ($do_wstring) {

Use {} instead of ().

> +	    gdb_test_no_output "set var \$wstr = L\"facile\"" \
> +		"set \$wstr, conv var"
> +	    gdb_test "printf \"wstr val = %ls\\n\", \$wstr" \
> +		"wstr val = facile" "printf \$wstr, conv var"
> +	}

All these "conv var" in the test names seem redundant, given the whole
proc body is wrapped in with_test_prefix.  How about replacing all
that with:

 -    with_test_prefix $prefix {
 +    with_test_prefix "conv var: $prefix" {

> +    }
> +}
> +
> +
>  # Start with a fresh gdb.
>  
>  gdb_exit
> @@ -948,6 +974,11 @@ gdb_test "ptype \"abc\"" " = char \\\[4\\\]"
>  gdb_test "print \$cvar = \"abc\"" " = \"abc\""
>  gdb_test "print sizeof (\$cvar)" " = 4"
>  
> +# Similarly, printf of convenience var should work without a target.

"of convenience var" -> "of a convenience var" or "of convenience vars".

Or maybe even: 

  printf of a string convenience var

> +# At this point, we cannot create wide strings convenience var, as the
> +# type wchar_t is not yet known, so skip the wide string tests.

"create wide strings convenience var" -> "create a wide string convenience var"

"wchar_t type" -> "wchar_t type"

> +test_printf_convenience_var "no target" 0
> +
>  # GDB used to complete the explicit location options even when
>  # printing expressions.
>  gdb_test_no_output "complete p -function"
> @@ -977,6 +1008,14 @@ if ![runto_main] then {
>      return 0
>  }
>  
> +# With a target, printf convenience var should of course work.

"With a running target"

"printf convenience vars"

> +test_printf_convenience_var "with target" 1
> +
> +# But it should also work when inferior function calls are forbidden.

"But it" -> "It".

> +gdb_test_no_output "set may-call-functions off"
> +test_printf_convenience_var "with target, may-call-functions off" 1
> +gdb_test_no_output "set may-call-functions on"
> +
>  test_integer_literals_accepted
>  test_integer_literals_rejected
>  test_float_accepted
> 

Thanks,
Pedro Alves

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

* Re: [RFA] Ensure GDB printf command can print convenience var strings without a target.
  2019-07-08 18:13 ` Pedro Alves
@ 2019-07-08 22:41   ` Philippe Waroquiers
  2019-07-09  4:36     ` New FAIL on gdb.base/printcmds.exp (was: Re: [RFA] Ensure GDB printf command can print convenience var strings without a target.) Sergio Durigan Junior
  0 siblings, 1 reply; 18+ messages in thread
From: Philippe Waroquiers @ 2019-07-08 22:41 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

On Mon, 2019-07-08 at 19:12 +0100, Pedro Alves wrote:
> Looks fine to me, with the nits below fixed.
Thanks.  I have applied all the suggested changes (except one)
and pushed the below patch as a result.

I kept 
  gdb_test "set language ada" ".*" "set language ada"
and clarified why with:
+	# Without a target, the below produces no output
+	# but with a target, it gives a warning.
+	# So, use gdb_test expecting ".*" instead of gdb_test_no_output.
+	gdb_test "set language ada" ".*" "set language ada"


Thanks for the review.

Philippe


From 1f6f6e21fa86dc3411a6498608f32e9eb24b7851 Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Mon, 10 Jun 2019 21:41:51 +0200
Subject: [PATCH] Ensure GDB printf command can print convenience var strings
 without a target.

Without this patch, GDB printf command calls malloc on the target,
writes the convenience var content to the target,
re-reads the content from the target, and then locally printf the string.

This implies inferior calls, and does not work when there is no running
inferior, or when the inferior is a core dump.

With this patch, printf command can printf string convenience variables
without inferior function calls.
Ada string convenience variables can also be printed.

gdb/ChangeLog
2019-07-08  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* NEWS: Mention that GDB printf and eval commands can now print
	C-style and Ada-style convenience var strings without
	calling the inferior.
	* printcmd.c (printf_c_string): Locally print GDB internal var
	instead of transiting via the inferior.
	(printf_wide_c_string): Likewise.

gdb/testsuite/ChangeLog
2019-07-08  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/printcmds.exp: Test printing C string and
	C wide string convenience vars without transiting via the inferior.
	Also make test names unique.
---
 gdb/ChangeLog                        |  11 ++-
 gdb/NEWS                             |   7 ++
 gdb/printcmd.c                       | 140 +++++++++++++++++----------
 gdb/testsuite/ChangeLog              |   6 ++
 gdb/testsuite/gdb.base/printcmds.exp |  59 ++++++++++-
 5 files changed, 165 insertions(+), 58 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 218bbf6223..2f406ae2bd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,4 +1,13 @@
-2019-08-04  Alan Hayward  <alan.hayward@arm.com>
+2019-07-08  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* NEWS: Mention that GDB printf and eval commands can now print
+	C-style and Ada-style convenience var strings without
+	calling the inferior.
+	* printcmd.c (printf_c_string): Locally print GDB internal var
+	instead of transiting via the inferior.
+	(printf_wide_c_string): Likewise.
+
+2019-07-04  Alan Hayward  <alan.hayward@arm.com>
 
 	* symfile.c (symbol_file_command): Call solib_create_inferior_hook.
 
diff --git a/gdb/NEWS b/gdb/NEWS
index 34c544c3d5..f7b6b88a22 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -118,6 +118,13 @@ apropos [-v] REGEXP
   of matching commands and to use the highlight style to mark
   the documentation parts matching REGEXP.
 
+printf
+eval
+  The GDB printf and eval commands can now print C-style and Ada-style
+  string convenience variables without calling functions in the program.
+  This allows to do formatted printing of strings without having
+  a running inferior, or when debugging a core dump.
+
 show style
   The "show style" and its subcommands are now styling
   a style name in their output using its own style, to help
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 0509360581..714a2e981e 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -23,6 +23,7 @@
 #include "gdbtypes.h"
 #include "value.h"
 #include "language.h"
+#include "c-lang.h"
 #include "expression.h"
 #include "gdbcore.h"
 #include "gdbcmd.h"
@@ -2222,42 +2223,64 @@ print_variable_and_value (const char *name, struct symbol *var,
 
 /* Subroutine of ui_printf to simplify it.
    Print VALUE to STREAM using FORMAT.
-   VALUE is a C-style string on the target.  */
+   VALUE is a C-style string either on the target or
+   in a GDB internal variable.  */
 
 static void
 printf_c_string (struct ui_file *stream, const char *format,
 		 struct value *value)
 {
-  gdb_byte *str;
-  CORE_ADDR tem;
-  int j;
+  const gdb_byte *str;
 
-  tem = value_as_address (value);
-  if (tem == 0)
+  if (VALUE_LVAL (value) == lval_internalvar
+      && c_is_string_type_p (value_type (value)))
     {
-      DIAGNOSTIC_PUSH
-      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-      fprintf_filtered (stream, format, "(null)");
-      DIAGNOSTIC_POP
-      return;
-    }
+      size_t len = TYPE_LENGTH (value_type (value));
 
-  /* This is a %s argument.  Find the length of the string.  */
-  for (j = 0;; j++)
-    {
-      gdb_byte c;
+      /* Copy the internal var value to TEM_STR and append a terminating null
+	 character.  This protects against corrupted C-style strings that lack
+	 the terminating null char.  It also allows Ada-style strings (not
+	 null terminated) to be printed without problems.  */
+      gdb_byte *tem_str = (gdb_byte *) alloca (len + 1);
 
-      QUIT;
-      read_memory (tem + j, &c, 1);
-      if (c == 0)
-	break;
+      memcpy (tem_str, value_contents (value), len);
+      tem_str [len] = 0;
+      str = tem_str;
     }
+  else
+    {
+      CORE_ADDR tem = value_as_address (value);;
+
+      if (tem == 0)
+	{
+	  DIAGNOSTIC_PUSH
+	  DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+	  fprintf_filtered (stream, format, "(null)");
+	  DIAGNOSTIC_POP
+	  return;
+	}
+
+      /* This is a %s argument.  Find the length of the string.  */
+      size_t len;
+
+      for (len = 0;; len++)
+	{
+	  gdb_byte c;
 
-  /* Copy the string contents into a string inside GDB.  */
-  str = (gdb_byte *) alloca (j + 1);
-  if (j != 0)
-    read_memory (tem, str, j);
-  str[j] = 0;
+	  QUIT;
+	  read_memory (tem + len, &c, 1);
+	  if (c == 0)
+	    break;
+	}
+
+      /* Copy the string contents into a string inside GDB.  */
+      gdb_byte *tem_str = (gdb_byte *) alloca (len + 1);
+
+      if (len != 0)
+	read_memory (tem, tem_str, len);
+      tem_str[len] = 0;
+      str = tem_str;
+    }
 
   DIAGNOSTIC_PUSH
   DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
@@ -2267,52 +2290,65 @@ printf_c_string (struct ui_file *stream, const char *format,
 
 /* Subroutine of ui_printf to simplify it.
    Print VALUE to STREAM using FORMAT.
-   VALUE is a wide C-style string on the target.  */
+   VALUE is a wide C-style string on the target or
+   in a GDB internal variable.  */
 
 static void
 printf_wide_c_string (struct ui_file *stream, const char *format,
 		      struct value *value)
 {
-  gdb_byte *str;
-  CORE_ADDR tem;
-  int j;
+  const gdb_byte *str;
+  size_t len;
   struct gdbarch *gdbarch = get_type_arch (value_type (value));
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct type *wctype = lookup_typename (current_language, gdbarch,
 					 "wchar_t", NULL, 0);
   int wcwidth = TYPE_LENGTH (wctype);
-  gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
 
-  tem = value_as_address (value);
-  if (tem == 0)
+  if (VALUE_LVAL (value) == lval_internalvar
+      && c_is_string_type_p (value_type (value)))
     {
-      DIAGNOSTIC_PUSH
-      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-      fprintf_filtered (stream, format, "(null)");
-      DIAGNOSTIC_POP
-      return;
+      str = value_contents (value);
+      len = TYPE_LENGTH (value_type (value));
     }
-
-  /* This is a %s argument.  Find the length of the string.  */
-  for (j = 0;; j += wcwidth)
+  else
     {
-      QUIT;
-      read_memory (tem + j, buf, wcwidth);
-      if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
-	break;
-    }
+      CORE_ADDR tem = value_as_address (value);
 
-  /* Copy the string contents into a string inside GDB.  */
-  str = (gdb_byte *) alloca (j + wcwidth);
-  if (j != 0)
-    read_memory (tem, str, j);
-  memset (&str[j], 0, wcwidth);
+      if (tem == 0)
+	{
+	  DIAGNOSTIC_PUSH
+	  DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+	  fprintf_filtered (stream, format, "(null)");
+	  DIAGNOSTIC_POP
+	  return;
+	}
+
+      /* This is a %s argument.  Find the length of the string.  */
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
+
+      for (len = 0;; len += wcwidth)
+	{
+	  QUIT;
+	  read_memory (tem + len, buf, wcwidth);
+	  if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
+	    break;
+	}
+
+      /* Copy the string contents into a string inside GDB.  */
+      gdb_byte *tem_str = (gdb_byte *) alloca (len + wcwidth);
+
+      if (len != 0)
+	read_memory (tem, tem_str, len);
+      memset (&tem_str[len], 0, wcwidth);
+      str = tem_str;
+    }
 
   auto_obstack output;
 
   convert_between_encodings (target_wide_charset (gdbarch),
 			     host_charset (),
-			     str, j, wcwidth,
+			     str, len, wcwidth,
 			     &output, translit_char);
   obstack_grow_str0 (&output, "");
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index a6d6843d96..f8ef540b4e 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2019-07-08  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* gdb.base/printcmds.exp: Test printing C string and
+	C wide string convenience vars without transiting via the inferior.
+	Also make test names unique.
+
 2019-07-08  Alan Hayward  <alan.hayward@arm.com>
 
 	* gdb.base/break-idempotent.exp: Test both PIE and non PIE.
diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
index f2d6ee229d..0e3126bcf2 100644
--- a/gdb/testsuite/gdb.base/printcmds.exp
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -438,7 +438,7 @@ proc test_print_repeats_10 {} {
     global gdb_prompt decimal
 
     for { set x 1 } { $x <= 16 } { incr x } {
-	gdb_test_no_output "set print elements $x"
+	gdb_test_no_output "set print elements $x" "elements $x repeats"
 	for { set e 1 } { $e <= 16 } {incr e } {
 	    set v [expr $e - 1]
 	    set command "p &ctable2\[${v}*16\]"
@@ -596,7 +596,7 @@ proc test_print_strings {} {
 proc test_print_int_arrays {} {
     global gdb_prompt
 
-    gdb_test_no_output "set print elements 24"
+    gdb_test_no_output "set print elements 24" "elements 24 int arrays"
 
     gdb_test_escape_braces "p int1dim" \
 	" = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}"
@@ -621,7 +621,7 @@ proc test_print_int_arrays {} {
 proc test_print_typedef_arrays {} {
     global gdb_prompt
 
-    gdb_test_no_output "set print elements 24"
+    gdb_test_no_output "set print elements 24" "elements 24 typedef_arrays"
 
     gdb_test_escape_braces "p a1" \
 	" = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}"
@@ -666,7 +666,7 @@ proc test_print_char_arrays {} {
     global gdb_prompt
     global hex decimal
 
-    gdb_test_no_output "set print elements 24"
+    gdb_test_no_output "set print elements 24" "elements 24 char_arrays"
     gdb_test_no_output "set print address on"
 
     gdb_test "p arrays" \
@@ -684,7 +684,7 @@ proc test_print_char_arrays {} {
     gdb_test "p parrays->array5"	" = \"hij\""
     gdb_test "p &parrays->array5"	" = \\(unsigned char \\(\\*\\)\\\[4\\\]\\) $hex <arrays\\+$decimal>"
 
-    gdb_test_no_output "set print address off"
+    gdb_test_no_output "set print address off" "address off char arrays"
 }
 
 proc test_print_string_constants {} {
@@ -932,6 +932,42 @@ proc test_repeat_bytes {} {
     }
 }
 
+# Test printf of convenience variables.
+# These tests can be done with or without a running inferior.
+# PREFIX ensures uniqueness of test names.
+# DO_WSTRING 1 tells to test printf of wide strings.  Wide strings tests
+# must be skipped (DO_WSTRING 0) if the wchar_t type is not yet known by
+# GDB, as this type is needed to create wide strings.
+
+proc test_printf_convenience_var {prefix do_wstring} {
+
+    with_test_prefix "conv var: $prefix" {
+	gdb_test_no_output "set var \$cstr = \"abcde\"" "set \$cstr"
+	gdb_test "printf \"cstr val = %s\\n\", \$cstr" "cstr val = abcde" \
+	    "printf \$cstr"
+	gdb_test_no_output "set var \$abcde = \"ABCDE\"" "set \$abcde"
+	gdb_test "eval \"print \$%s\\n\", \$cstr" "= \"ABCDE\"" \
+	    "indirect print abcde"
+	# Without a target, the below produces no output
+	# but with a target, it gives a warning.
+	# So, use gdb_test expecting ".*" instead of gdb_test_no_output.
+	gdb_test "set language ada" ".*" "set language ada"
+	gdb_test_no_output "set var \$astr := \"fghij\"" "set \$astr"
+	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
+	    "printf \$astr"
+	gdb_test_no_output "set language auto" "set language auto"
+	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
+	    "printf \$astr, auto language"
+	if {$do_wstring} {
+	    gdb_test_no_output "set var \$wstr = L\"facile\"" \
+		"set \$wstr"
+	    gdb_test "printf \"wstr val = %ls\\n\", \$wstr" \
+		"wstr val = facile" "printf \$wstr"
+	}
+    }
+}
+
+
 # Start with a fresh gdb.
 
 gdb_exit
@@ -948,6 +984,11 @@ gdb_test "ptype \"abc\"" " = char \\\[4\\\]"
 gdb_test "print \$cvar = \"abc\"" " = \"abc\""
 gdb_test "print sizeof (\$cvar)" " = 4"
 
+# Similarly, printf of a string convenience var should work without a target.
+# At this point, we cannot create a wide string convenience var, as the
+# wchar_t type is not yet known, so skip the wide string tests.
+test_printf_convenience_var "no target" 0
+
 # GDB used to complete the explicit location options even when
 # printing expressions.
 gdb_test_no_output "complete p -function"
@@ -977,6 +1018,14 @@ if ![runto_main] then {
     return 0
 }
 
+# With a running target, printf convenience vars should of course work.
+test_printf_convenience_var "with target" 1
+
+# It should also work when inferior function calls are forbidden.
+gdb_test_no_output "set may-call-functions off"
+test_printf_convenience_var "with target, may-call-functions off" 1
+gdb_test_no_output "set may-call-functions on"
+
 test_integer_literals_accepted
 test_integer_literals_rejected
 test_float_accepted
-- 
2.20.1

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

* New FAIL on gdb.base/printcmds.exp (was: Re: [RFA] Ensure GDB printf command can print convenience var strings without a target.)
  2019-07-08 22:41   ` Philippe Waroquiers
@ 2019-07-09  4:36     ` Sergio Durigan Junior
  0 siblings, 0 replies; 18+ messages in thread
From: Sergio Durigan Junior @ 2019-07-09  4:36 UTC (permalink / raw)
  To: Philippe Waroquiers; +Cc: Pedro Alves, gdb-patches

On Monday, July 08 2019, Philippe Waroquiers wrote:

> On Mon, 2019-07-08 at 19:12 +0100, Pedro Alves wrote:
>> Looks fine to me, with the nits below fixed.
> Thanks.  I have applied all the suggested changes (except one)
> and pushed the below patch as a result.
>
> I kept 
>   gdb_test "set language ada" ".*" "set language ada"
> and clarified why with:
> +	# Without a target, the below produces no output
> +	# but with a target, it gives a warning.
> +	# So, use gdb_test expecting ".*" instead of gdb_test_no_output.
> +	gdb_test "set language ada" ".*" "set language ada"

Hi Philippe,

I'm seeing new FAILures on gdb.base/printcmds.exp:

  new FAIL: gdb.base/printcmds.exp: conv var: with target, may-call-functions off: printf $wstr
  new FAIL: gdb.base/printcmds.exp: conv var: with target, may-call-functions off: set $wstr
  new FAIL: gdb.base/printcmds.exp: conv var: with target: printf $wstr
  new FAIL: gdb.base/printcmds.exp: conv var: with target: set $wstr

The BuildBot has caught them:

  https://sourceware.org/ml/gdb-testers/2019-q3/msg00361.html

The problem happens because GDB can't identify the wchar_t type:

  set var $wstr = L"facile"
  No type named wchar_t.
  (gdb) FAIL: gdb.base/printcmds.exp: conv var: with target: set $wstr

The patch below fixes the problem for me.  wchar_t is built-in on C++,
so the trick is to set the language to "c++" before dealing with it (and
restore the language back to "auto" later).  WDYT?

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/

gdb/testsuite/ChangeLog:
2019-07-09  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/printcmds.exp (test_printf_convenience_var): Set
	language to "c++" before dealing with wchar_t.

diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
index 0e3126bcf2..aaa4d8d07d 100644
--- a/gdb/testsuite/gdb.base/printcmds.exp
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -959,10 +959,12 @@ proc test_printf_convenience_var {prefix do_wstring} {
 	gdb_test "printf \"astr val = %s\\n\", \$astr" "astr val = fghij" \
 	    "printf \$astr, auto language"
 	if {$do_wstring} {
+	    gdb_test_no_output "set language c++"
 	    gdb_test_no_output "set var \$wstr = L\"facile\"" \
 		"set \$wstr"
 	    gdb_test "printf \"wstr val = %ls\\n\", \$wstr" \
 		"wstr val = facile" "printf \$wstr"
+	    gdb_test_no_output "set language auto"
 	}
     }
 }

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

* [PATCH] Fix printf of a convenience variable holding an inferior address
  2019-06-10 21:16 [RFA] Ensure GDB printf command can print convenience var strings without a target Philippe Waroquiers
                   ` (2 preceding siblings ...)
  2019-07-08 18:13 ` Pedro Alves
@ 2020-03-02  2:46 ` Sergio Durigan Junior
  2020-03-03 13:39   ` Andrew Burgess
  3 siblings, 1 reply; 18+ messages in thread
From: Sergio Durigan Junior @ 2020-03-02  2:46 UTC (permalink / raw)
  To: GDB Patches; +Cc: Philippe Waroquiers, Pedro Alves, Sergio Durigan Junior

Back at:

commit 1f6f6e21fa86dc3411a6498608f32e9eb24b7851
Author: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date:   Mon Jun 10 21:41:51 2019 +0200

    Ensure GDB printf command can print convenience var strings without a target.

GDB was extended in order to allow the printing of convenience
variables that are strings without a target.  However, this introduced
a regression that hasn't been caught by our testsuite (because there
were no tests for it).

The problem happens when we try to print a convenience variable that
holds the address of a string in the inferior.  The following
two-liners can reproduce the issue:

$ echo -e 'int main(){const char a[]="test";return 0;}' | gcc -x c - -O0-g3
$ ./gdb/gdb --data-directory ./gdb/data-directory -q ./a.out -ex 'start' -ex 'set $x = (const char *) (&a[0] + 2)' -ex 'printf "%s\n", $x'

After some investigation, I found that the problem happens on
printcmd.c:printf_c_string.  In the case above, we're taking the first
branch of the 'if' condition, which assumes that there will be a value
to be printed at "value_contents (value)".  There isn't.  We actually
need to obtain the address that the variable points to, and read the
contents from memory.

It seems to me that we should avoid this branch if the TYPE_CODE of
"value_type (value)" is TYPE_CODE_PTR (i.e., a pointer to the
inferior's memory).  This is what this patch does.

I took the liberty to extend the current testcase under
gdb.base/printcmds.exp and create a test that exercises this scenario.

No regressions have been found on Buildbot.

gdb/ChangeLog:
2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>

	* printcmd.c (print_c_string): Check also for TYPE_CODE_PTR
	when verifying if dealing with a convenience variable.

gdb/testsuite/ChangeLog:
2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/printcmds.exp: Add test to verify printf of a
	variable holding an address.
---
 gdb/printcmd.c                       | 3 ++-
 gdb/testsuite/gdb.base/printcmds.exp | 8 ++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 797041484e..78d8d3d81e 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -2260,7 +2260,8 @@ printf_c_string (struct ui_file *stream, const char *format,
 {
   const gdb_byte *str;
 
-  if (VALUE_LVAL (value) == lval_internalvar
+  if (TYPE_CODE (value_type (value)) != TYPE_CODE_PTR
+      && VALUE_LVAL (value) == lval_internalvar
       && c_is_string_type_p (value_type (value)))
     {
       size_t len = TYPE_LENGTH (value_type (value));
diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
index bd2afc8696..c87a1517f0 100644
--- a/gdb/testsuite/gdb.base/printcmds.exp
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -1039,6 +1039,14 @@ gdb_test_no_output "set may-call-functions off"
 test_printf_convenience_var "with target, may-call-functions off"
 gdb_test_no_output "set may-call-functions on"
 
+# Test printf of a variable that holds the address to a substring in
+# the inferior.  This test will not work without a target.
+gdb_test_no_output "set var \$test_substr = \(char \*\) \(&teststring\[0\] + 4\)" \
+    "set \$test_substr var"
+gdb_test "printf \"test_substr val = %s\\n\", \$test_substr" \
+    "test_substr val = string contents" \
+    "print \$test_substr"
+
 test_integer_literals_accepted
 test_integer_literals_rejected
 test_float_accepted
-- 
2.24.1

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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-02  2:46 ` [PATCH] Fix printf of a convenience variable holding an inferior address Sergio Durigan Junior
@ 2020-03-03 13:39   ` Andrew Burgess
  2020-03-03 16:29     ` Sergio Durigan Junior
  0 siblings, 1 reply; 18+ messages in thread
From: Andrew Burgess @ 2020-03-03 13:39 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches, Philippe Waroquiers, Pedro Alves

* Sergio Durigan Junior <sergiodj@redhat.com> [2020-03-01 21:46:16 -0500]:

> Back at:
> 
> commit 1f6f6e21fa86dc3411a6498608f32e9eb24b7851
> Author: Philippe Waroquiers <philippe.waroquiers@skynet.be>
> Date:   Mon Jun 10 21:41:51 2019 +0200
> 
>     Ensure GDB printf command can print convenience var strings without a target.
> 
> GDB was extended in order to allow the printing of convenience
> variables that are strings without a target.  However, this introduced
> a regression that hasn't been caught by our testsuite (because there
> were no tests for it).
> 
> The problem happens when we try to print a convenience variable that
> holds the address of a string in the inferior.  The following
> two-liners can reproduce the issue:
> 
> $ echo -e 'int main(){const char a[]="test";return 0;}' | gcc -x c - -O0-g3
> $ ./gdb/gdb --data-directory ./gdb/data-directory -q ./a.out -ex 'start' -ex 'set $x = (const char *) (&a[0] + 2)' -ex 'printf "%s\n", $x'
> 
> After some investigation, I found that the problem happens on
> printcmd.c:printf_c_string.  In the case above, we're taking the first
> branch of the 'if' condition, which assumes that there will be a value
> to be printed at "value_contents (value)".  There isn't.  We actually
> need to obtain the address that the variable points to, and read the
> contents from memory.
> 
> It seems to me that we should avoid this branch if the TYPE_CODE of
> "value_type (value)" is TYPE_CODE_PTR (i.e., a pointer to the
> inferior's memory).  This is what this patch does.
> 
> I took the liberty to extend the current testcase under
> gdb.base/printcmds.exp and create a test that exercises this scenario.
> 
> No regressions have been found on Buildbot.
> 
> gdb/ChangeLog:
> 2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* printcmd.c (print_c_string): Check also for TYPE_CODE_PTR
> 	when verifying if dealing with a convenience variable.
> 
> gdb/testsuite/ChangeLog:
> 2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* gdb.base/printcmds.exp: Add test to verify printf of a
> 	variable holding an address.

LGTM.

Thanks,
Andrew


> ---
>  gdb/printcmd.c                       | 3 ++-
>  gdb/testsuite/gdb.base/printcmds.exp | 8 ++++++++
>  2 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index 797041484e..78d8d3d81e 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -2260,7 +2260,8 @@ printf_c_string (struct ui_file *stream, const char *format,
>  {
>    const gdb_byte *str;
>  
> -  if (VALUE_LVAL (value) == lval_internalvar
> +  if (TYPE_CODE (value_type (value)) != TYPE_CODE_PTR
> +      && VALUE_LVAL (value) == lval_internalvar
>        && c_is_string_type_p (value_type (value)))
>      {
>        size_t len = TYPE_LENGTH (value_type (value));
> diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
> index bd2afc8696..c87a1517f0 100644
> --- a/gdb/testsuite/gdb.base/printcmds.exp
> +++ b/gdb/testsuite/gdb.base/printcmds.exp
> @@ -1039,6 +1039,14 @@ gdb_test_no_output "set may-call-functions off"
>  test_printf_convenience_var "with target, may-call-functions off"
>  gdb_test_no_output "set may-call-functions on"
>  
> +# Test printf of a variable that holds the address to a substring in
> +# the inferior.  This test will not work without a target.
> +gdb_test_no_output "set var \$test_substr = \(char \*\) \(&teststring\[0\] + 4\)" \
> +    "set \$test_substr var"
> +gdb_test "printf \"test_substr val = %s\\n\", \$test_substr" \
> +    "test_substr val = string contents" \
> +    "print \$test_substr"
> +
>  test_integer_literals_accepted
>  test_integer_literals_rejected
>  test_float_accepted
> -- 
> 2.24.1
> 

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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-03 13:39   ` Andrew Burgess
@ 2020-03-03 16:29     ` Sergio Durigan Junior
  2020-03-03 16:49       ` Sergio Durigan Junior
  0 siblings, 1 reply; 18+ messages in thread
From: Sergio Durigan Junior @ 2020-03-03 16:29 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: GDB Patches, Philippe Waroquiers, Pedro Alves

On Tuesday, March 03 2020, Andrew Burgess wrote:

> * Sergio Durigan Junior <sergiodj@redhat.com> [2020-03-01 21:46:16 -0500]:
>
>> Back at:
>> 
>> commit 1f6f6e21fa86dc3411a6498608f32e9eb24b7851
>> Author: Philippe Waroquiers <philippe.waroquiers@skynet.be>
>> Date:   Mon Jun 10 21:41:51 2019 +0200
>> 
>>     Ensure GDB printf command can print convenience var strings without a target.
>> 
>> GDB was extended in order to allow the printing of convenience
>> variables that are strings without a target.  However, this introduced
>> a regression that hasn't been caught by our testsuite (because there
>> were no tests for it).
>> 
>> The problem happens when we try to print a convenience variable that
>> holds the address of a string in the inferior.  The following
>> two-liners can reproduce the issue:
>> 
>> $ echo -e 'int main(){const char a[]="test";return 0;}' | gcc -x c - -O0-g3
>> $ ./gdb/gdb --data-directory ./gdb/data-directory -q ./a.out -ex 'start' -ex 'set $x = (const char *) (&a[0] + 2)' -ex 'printf "%s\n", $x'
>> 
>> After some investigation, I found that the problem happens on
>> printcmd.c:printf_c_string.  In the case above, we're taking the first
>> branch of the 'if' condition, which assumes that there will be a value
>> to be printed at "value_contents (value)".  There isn't.  We actually
>> need to obtain the address that the variable points to, and read the
>> contents from memory.
>> 
>> It seems to me that we should avoid this branch if the TYPE_CODE of
>> "value_type (value)" is TYPE_CODE_PTR (i.e., a pointer to the
>> inferior's memory).  This is what this patch does.
>> 
>> I took the liberty to extend the current testcase under
>> gdb.base/printcmds.exp and create a test that exercises this scenario.
>> 
>> No regressions have been found on Buildbot.
>> 
>> gdb/ChangeLog:
>> 2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* printcmd.c (print_c_string): Check also for TYPE_CODE_PTR
>> 	when verifying if dealing with a convenience variable.
>> 
>> gdb/testsuite/ChangeLog:
>> 2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* gdb.base/printcmds.exp: Add test to verify printf of a
>> 	variable holding an address.
>
> LGTM.

Thanks, pushed:

7b973adce2b486518d3150db257b179e1b9a5d33

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/

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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-03 16:29     ` Sergio Durigan Junior
@ 2020-03-03 16:49       ` Sergio Durigan Junior
  2020-03-04 10:53         ` Joel Brobecker
  0 siblings, 1 reply; 18+ messages in thread
From: Sergio Durigan Junior @ 2020-03-03 16:49 UTC (permalink / raw)
  To: Andrew Burgess
  Cc: GDB Patches, Philippe Waroquiers, Pedro Alves, Joel Brobecker

On Tuesday, March 03 2020, I wrote:

> On Tuesday, March 03 2020, Andrew Burgess wrote:
>
>> * Sergio Durigan Junior <sergiodj@redhat.com> [2020-03-01 21:46:16 -0500]:
>>
>>> Back at:
>>> 
>>> commit 1f6f6e21fa86dc3411a6498608f32e9eb24b7851
>>> Author: Philippe Waroquiers <philippe.waroquiers@skynet.be>
>>> Date:   Mon Jun 10 21:41:51 2019 +0200
>>> 
>>>     Ensure GDB printf command can print convenience var strings without a target.
>>> 
>>> GDB was extended in order to allow the printing of convenience
>>> variables that are strings without a target.  However, this introduced
>>> a regression that hasn't been caught by our testsuite (because there
>>> were no tests for it).
>>> 
>>> The problem happens when we try to print a convenience variable that
>>> holds the address of a string in the inferior.  The following
>>> two-liners can reproduce the issue:
>>> 
>>> $ echo -e 'int main(){const char a[]="test";return 0;}' | gcc -x c - -O0-g3
>>> $ ./gdb/gdb --data-directory ./gdb/data-directory -q ./a.out -ex 'start' -ex 'set $x = (const char *) (&a[0] + 2)' -ex 'printf "%s\n", $x'
>>> 
>>> After some investigation, I found that the problem happens on
>>> printcmd.c:printf_c_string.  In the case above, we're taking the first
>>> branch of the 'if' condition, which assumes that there will be a value
>>> to be printed at "value_contents (value)".  There isn't.  We actually
>>> need to obtain the address that the variable points to, and read the
>>> contents from memory.
>>> 
>>> It seems to me that we should avoid this branch if the TYPE_CODE of
>>> "value_type (value)" is TYPE_CODE_PTR (i.e., a pointer to the
>>> inferior's memory).  This is what this patch does.
>>> 
>>> I took the liberty to extend the current testcase under
>>> gdb.base/printcmds.exp and create a test that exercises this scenario.
>>> 
>>> No regressions have been found on Buildbot.
>>> 
>>> gdb/ChangeLog:
>>> 2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>
>>> 
>>> 	* printcmd.c (print_c_string): Check also for TYPE_CODE_PTR
>>> 	when verifying if dealing with a convenience variable.
>>> 
>>> gdb/testsuite/ChangeLog:
>>> 2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>
>>> 
>>> 	* gdb.base/printcmds.exp: Add test to verify printf of a
>>> 	variable holding an address.
>>
>> LGTM.
>
> Thanks, pushed:
>
> 7b973adce2b486518d3150db257b179e1b9a5d33

BTW, this also affects 9.1 (in fact, that's where I found the bug).  I
can create a tracking bug and backport it to the branch if the issue and
fix are deemed important enough.

Thanks,

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/

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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-03 16:49       ` Sergio Durigan Junior
@ 2020-03-04 10:53         ` Joel Brobecker
       [not found]           ` <8736al5d8s.fsf@redhat.com>
  0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2020-03-04 10:53 UTC (permalink / raw)
  To: Sergio Durigan Junior
  Cc: Andrew Burgess, GDB Patches, Philippe Waroquiers, Pedro Alves

Hi Sergio,

> >>> gdb/ChangeLog:
> >>> 2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>
> >>> 
> >>> 	* printcmd.c (print_c_string): Check also for TYPE_CODE_PTR
> >>> 	when verifying if dealing with a convenience variable.
> >>> 
> >>> gdb/testsuite/ChangeLog:
> >>> 2020-03-02  Sergio Durigan Junior  <sergiodj@redhat.com>
> >>> 
> >>> 	* gdb.base/printcmds.exp: Add test to verify printf of a
> >>> 	variable holding an address.
> >>
> >> LGTM.
> >
> > Thanks, pushed:
> >
> > 7b973adce2b486518d3150db257b179e1b9a5d33
> 
> BTW, this also affects 9.1 (in fact, that's where I found the bug).  I
> can create a tracking bug and backport it to the branch if the issue and
> fix are deemed important enough.

Do you know if this issue is a regression, compared to previous
released versions?

In terms of putting it in 9.2, I think we could do it; the patch
does look safe to me.

-- 
Joel

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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
       [not found]           ` <8736al5d8s.fsf@redhat.com>
@ 2020-03-07 11:58             ` Joel Brobecker
  2020-03-09 22:56               ` Sergio Durigan Junior
  0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2020-03-07 11:58 UTC (permalink / raw)
  To: Sergio Durigan Junior
  Cc: Andrew Burgess, GDB Patches, Philippe Waroquiers, Pedro Alves

> Yeah, this is a regression.  GDB 8.3 worked fine.

OK. Thanks for confirming, Sergio.

> > In terms of putting it in 9.2, I think we could do it; the patch
> > does look safe to me.
> 
> Cool.  So, is the process the same (now that we're using a different
> versioning scheme)?  Do I just open a bug again 9.1 and push the
> backported patch to the branch?

Correct :). If you don't mind, it might be useful to amend the
ChangeLog entry in master to include the PR number.

Thanks Sergio!
-- 
Joel

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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-07 11:58             ` Joel Brobecker
@ 2020-03-09 22:56               ` Sergio Durigan Junior
  2020-03-10 22:37                 ` Joel Brobecker
  0 siblings, 1 reply; 18+ messages in thread
From: Sergio Durigan Junior @ 2020-03-09 22:56 UTC (permalink / raw)
  To: Joel Brobecker
  Cc: Andrew Burgess, GDB Patches, Philippe Waroquiers, Pedro Alves

On Saturday, March 07 2020, Joel Brobecker wrote:

>> Yeah, this is a regression.  GDB 8.3 worked fine.
>
> OK. Thanks for confirming, Sergio.
>
>> > In terms of putting it in 9.2, I think we could do it; the patch
>> > does look safe to me.
>> 
>> Cool.  So, is the process the same (now that we're using a different
>> versioning scheme)?  Do I just open a bug again 9.1 and push the
>> backported patch to the branch?
>
> Correct :). If you don't mind, it might be useful to amend the
> ChangeLog entry in master to include the PR number.

Alright, I just pushed a new commit to the gdb-9-branch:

https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=141e490226a99e0359393ddaca5628c68de036dc

The bug is:

https://sourceware.org/bugzilla/show_bug.cgi?id=25650

I didn't set the Target Milestone there because I didn't see a "9.2" (or
"9.1.1"?) option.

Let me know if there's anything else I need to do :-).

> Thanks Sergio!

Thank you!

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/


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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-09 22:56               ` Sergio Durigan Junior
@ 2020-03-10 22:37                 ` Joel Brobecker
  2020-03-10 22:57                   ` Sergio Durigan Junior
  2020-03-11 16:34                   ` Sergio Durigan Junior
  0 siblings, 2 replies; 18+ messages in thread
From: Joel Brobecker @ 2020-03-10 22:37 UTC (permalink / raw)
  To: Sergio Durigan Junior
  Cc: Andrew Burgess, GDB Patches, Philippe Waroquiers, Pedro Alves

Hi Sergio,

> Alright, I just pushed a new commit to the gdb-9-branch:
> 
> https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=141e490226a99e0359393ddaca5628c68de036dc
> 
> The bug is:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=25650

Thank you!

> I didn't set the Target Milestone there because I didn't see a "9.2" (or
> "9.1.1"?) option.

Indeed. Can you ask overseers to add "9.2"?

It's important to have the target milestone set, because my scripts
automatically fetches the list of PRs based on that target milestone,
in order to produce the list of changes in the .2.

-- 
Joel

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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-10 22:37                 ` Joel Brobecker
@ 2020-03-10 22:57                   ` Sergio Durigan Junior
  2020-03-10 23:13                     ` Andreas Schwab
  2020-03-11 16:34                   ` Sergio Durigan Junior
  1 sibling, 1 reply; 18+ messages in thread
From: Sergio Durigan Junior @ 2020-03-10 22:57 UTC (permalink / raw)
  To: Joel Brobecker
  Cc: Andrew Burgess, GDB Patches, Philippe Waroquiers, Pedro Alves

On Tuesday, March 10 2020, Joel Brobecker wrote:

>> I didn't set the Target Milestone there because I didn't see a "9.2" (or
>> "9.1.1"?) option.
>
> Indeed. Can you ask overseers to add "9.2"?

Sure thing.

I think they're busy right now with the migration, but I'll make sure to
ask them when things calm down.

Thanks,

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/


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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-10 22:57                   ` Sergio Durigan Junior
@ 2020-03-10 23:13                     ` Andreas Schwab
  2020-03-10 23:38                       ` Sergio Durigan Junior
  0 siblings, 1 reply; 18+ messages in thread
From: Andreas Schwab @ 2020-03-10 23:13 UTC (permalink / raw)
  To: Sergio Durigan Junior via Gdb-patches
  Cc: Joel Brobecker, Sergio Durigan Junior, Pedro Alves

On Mär 10 2020, Sergio Durigan Junior via Gdb-patches wrote:

> On Tuesday, March 10 2020, Joel Brobecker wrote:
>
>>> I didn't set the Target Milestone there because I didn't see a "9.2" (or
>>> "9.1.1"?) option.
>>
>> Indeed. Can you ask overseers to add "9.2"?
>
> Sure thing.
>
> I think they're busy right now with the migration, but I'll make sure to
> ask them when things calm down.

I just did it.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-10 23:13                     ` Andreas Schwab
@ 2020-03-10 23:38                       ` Sergio Durigan Junior
  0 siblings, 0 replies; 18+ messages in thread
From: Sergio Durigan Junior @ 2020-03-10 23:38 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Sergio Durigan Junior via Gdb-patches, Joel Brobecker, Pedro Alves

On Tuesday, March 10 2020, Andreas Schwab wrote:

> On Mär 10 2020, Sergio Durigan Junior via Gdb-patches wrote:
>
>> On Tuesday, March 10 2020, Joel Brobecker wrote:
>>
>>>> I didn't set the Target Milestone there because I didn't see a "9.2" (or
>>>> "9.1.1"?) option.
>>>
>>> Indeed. Can you ask overseers to add "9.2"?
>>
>> Sure thing.
>>
>> I think they're busy right now with the migration, but I'll make sure to
>> ask them when things calm down.
>
> I just did it.

Thanks, but I don't see it in the list.  I think you added a "9.2"
Version, instead of the Target Milestone?

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/


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

* Re: [PATCH] Fix printf of a convenience variable holding an inferior address
  2020-03-10 22:37                 ` Joel Brobecker
  2020-03-10 22:57                   ` Sergio Durigan Junior
@ 2020-03-11 16:34                   ` Sergio Durigan Junior
  1 sibling, 0 replies; 18+ messages in thread
From: Sergio Durigan Junior @ 2020-03-11 16:34 UTC (permalink / raw)
  To: Joel Brobecker
  Cc: Andrew Burgess, GDB Patches, Philippe Waroquiers, Pedro Alves

On Tuesday, March 10 2020, Joel Brobecker wrote:

> Hi Sergio,
>
>> Alright, I just pushed a new commit to the gdb-9-branch:
>> 
>> https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=141e490226a99e0359393ddaca5628c68de036dc
>> 
>> The bug is:
>> 
>> https://sourceware.org/bugzilla/show_bug.cgi?id=25650
>
> Thank you!
>
>> I didn't set the Target Milestone there because I didn't see a "9.2" (or
>> "9.1.1"?) option.
>
> Indeed. Can you ask overseers to add "9.2"?
>
> It's important to have the target milestone set, because my scripts
> automatically fetches the list of PRs based on that target milestone,
> in order to produce the list of changes in the .2.

FWIW, Frank gave me admin rights on the bugzilla and I created the 9.2
target milestone (and assigned the bug to it).

Thanks,

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/


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

end of thread, other threads:[~2020-03-11 16:34 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-10 21:16 [RFA] Ensure GDB printf command can print convenience var strings without a target Philippe Waroquiers
2019-06-11  2:29 ` Eli Zaretskii
2019-07-05 20:01 ` PING " Philippe Waroquiers
2019-07-08 18:13 ` Pedro Alves
2019-07-08 22:41   ` Philippe Waroquiers
2019-07-09  4:36     ` New FAIL on gdb.base/printcmds.exp (was: Re: [RFA] Ensure GDB printf command can print convenience var strings without a target.) Sergio Durigan Junior
2020-03-02  2:46 ` [PATCH] Fix printf of a convenience variable holding an inferior address Sergio Durigan Junior
2020-03-03 13:39   ` Andrew Burgess
2020-03-03 16:29     ` Sergio Durigan Junior
2020-03-03 16:49       ` Sergio Durigan Junior
2020-03-04 10:53         ` Joel Brobecker
     [not found]           ` <8736al5d8s.fsf@redhat.com>
2020-03-07 11:58             ` Joel Brobecker
2020-03-09 22:56               ` Sergio Durigan Junior
2020-03-10 22:37                 ` Joel Brobecker
2020-03-10 22:57                   ` Sergio Durigan Junior
2020-03-10 23:13                     ` Andreas Schwab
2020-03-10 23:38                       ` Sergio Durigan Junior
2020-03-11 16:34                   ` Sergio Durigan Junior

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).