public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Handle %I64d in format_pieces
@ 2019-11-21 21:43 Tom Tromey
  0 siblings, 0 replies; only message in thread
From: Tom Tromey @ 2019-11-21 21:43 UTC (permalink / raw)
  To: gdb-cvs

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

commit 6ba185213659517b4299a3e4c92813839f19f045
Author: Tom Tromey <tromey@adacore.com>
Date:   Thu Nov 14 15:00:19 2019 -0700

    Handle %I64d in format_pieces
    
    We found a bug internally where gdb would crash while disassembling a
    certain instruction.  This was tracked down to the handling of %I64d
    in format_pieces.
    
    format_pieces will convert %ll to %I64d on mingw -- so format_pieces
    should also handle parsing this format.  In this patch, I've made the
    parsing unconditional, since I think it is harmless to accept extra
    formats.  I've also taken the opportunity to convert the length
    modifier test to a "switch".
    
    Tested internally using our failing test case.
    
    gdb/ChangeLog
    2019-11-21  Tom Tromey  <tromey@adacore.com>
    
    	* gdbsupport/format.c (format_pieces): Parse %I64d.
    	* unittests/format_pieces-selftests.c (test_windows_formats): New
    	function.
    	(run_tests): Call it.
    
    Change-Id: If335c7c2fc8d01e629cd55182394a483334d79c7

Diff:
---
 gdb/ChangeLog                           |  7 +++++
 gdb/gdbsupport/format.c                 | 51 +++++++++++++++++++--------------
 gdb/unittests/format_pieces-selftests.c | 11 +++++++
 3 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0249048..0c81de4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2019-11-21  Tom Tromey  <tromey@adacore.com>
+
+	* gdbsupport/format.c (format_pieces): Parse %I64d.
+	* unittests/format_pieces-selftests.c (test_windows_formats): New
+	function.
+	(run_tests): Call it.
+
 2019-11-21  Peeter Joot  <peeter.joot@lzlabs.com>
 
 	Byte reverse display of variables with DW_END_big, DW_END_little
diff --git a/gdb/gdbsupport/format.c b/gdb/gdbsupport/format.c
index 2e2d90a..67daa6d 100644
--- a/gdb/gdbsupport/format.c
+++ b/gdb/gdbsupport/format.c
@@ -126,6 +126,7 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions)
 	int seen_size_t = 0;
 	int bad = 0;
 	int n_int_args = 0;
+	bool seen_i64 = false;
 
 	/* Skip over "%%", it will become part of a literal piece.  */
 	if (*f == '%')
@@ -195,13 +196,13 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions)
 	  }
 
 	/* The next part of a format specifier is a length modifier.  */
-	if (*f == 'h')
+	switch (*f)
 	  {
+	  case 'h':
 	    seen_h = 1;
 	    f++;
-	  }
-	else if (*f == 'l')
-	  {
+	    break;
+	  case 'l':
 	    f++;
 	    lcount++;
 	    if (*f == 'l')
@@ -209,21 +210,18 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions)
 		f++;
 		lcount++;
 	      }
-	  }
-	else if (*f == 'L')
-	  {
+	    break;
+	  case 'L':
 	    seen_big_l = 1;
 	    f++;
-	  }
-	/* Decimal32 modifier.  */
-	else if (*f == 'H')
-	  {
+	    break;
+	  case 'H':
+	    /* Decimal32 modifier.  */
 	    seen_big_h = 1;
 	    f++;
-	  }
-	/* Decimal64 and Decimal128 modifiers.  */
-	else if (*f == 'D')
-	  {
+	    break;
+	  case 'D':
+	    /* Decimal64 and Decimal128 modifiers.  */
 	    f++;
 
 	    /* Check for a Decimal128.  */
@@ -234,13 +232,24 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions)
 	      }
 	    else
 	      seen_big_d = 1;
-	  }
-	/* For size_t or ssize_t.  */
-	else if (*f == 'z')
-	  {
+	    break;
+	  case 'z':
+	    /* For size_t or ssize_t.  */
 	    seen_size_t = 1;
 	    f++;
-	  }
+	    break;
+	  case 'I':
+	    /* Support the Windows '%I64' extension, because an
+	       earlier call to format_pieces might have converted %lld
+	       to %I64d.  */
+	    if (f[1] == '6' && f[2] == '4')
+	      {
+		f += 3;
+		lcount = 2;
+		seen_i64 = true;
+	      }
+	    break;
+	}
 
 	switch (*f)
 	  {
@@ -353,7 +362,7 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions)
 
 	sub_start = current_substring;
 
-	if (lcount > 1 && USE_PRINTF_I64)
+	if (lcount > 1 && !seen_i64 && USE_PRINTF_I64)
 	  {
 	    /* Windows' printf does support long long, but not the usual way.
 	       Convert %lld to %I64d.  */
diff --git a/gdb/unittests/format_pieces-selftests.c b/gdb/unittests/format_pieces-selftests.c
index 3971201..d7e97d4 100644
--- a/gdb/unittests/format_pieces-selftests.c
+++ b/gdb/unittests/format_pieces-selftests.c
@@ -120,12 +120,23 @@ test_format_int_sizes ()
 }
 
 static void
+test_windows_formats ()
+{
+  check ("rc%I64d",
+    {
+     format_piece ("rc", literal_piece, 0),
+     format_piece ("%I64d", long_long_arg, 0),
+    });
+}
+
+static void
 run_tests ()
 {
   test_escape_sequences ();
   test_format_specifier ();
   test_gdb_formats ();
   test_format_int_sizes ();
+  test_windows_formats ();
 }
 
 } /* namespace format_pieces */


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2019-11-21 21:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-21 21:43 [binutils-gdb] Handle %I64d in format_pieces Tom Tromey

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