gdb: Support printf 'z' size modifier
authorAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 5 Nov 2019 14:24:17 +0000 (14:24 +0000)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 12 Nov 2019 23:46:41 +0000 (23:46 +0000)
The gdb format mechanism doesn't currently support the 'z' size
modifier, there are a few places in GDB where this is used.  Instead
of removing these uses lets just add support to GDB for using 'z'.

I found this issue when trying to use some of the debug output.
Before this commit:

  (gdb) set debug dwarf-line 9
  (gdb) file test
  Reading symbols from test...
  Unrecognized format specifier 'z' in printf
  (No debugging symbols found in test)
  (gdb)

After this commit:

  (gdb) set debug dwarf-line 9
  (gdb) file test
  Reading symbols from test...
  Adding dir 1: /usr/include
  Adding file 1: test.c
  Adding file 2: stdc-predef.h
  Processing actual line 3: file 1, address 0x4004a0, is_stmt 1, discrim 0
  Processing actual line 4: file 1, address 0x4004a0, is_stmt 1, discrim 0
  .... lots of debug output ...
  Processing actual line 10: file 1, address 0x4003b7, is_stmt 0, discrim 0
  (gdb)

I've added a self test to cover the integer format size modifiers,
including the 'z' modifier.

gdb/ChangeLog:

* gdbsupport/format.c (format_pieces::format_pieces): Support
printf 'z' size modifier.
* gdbsupport/format.h (enum argclass): Add size_t_arg.
* printcmd.c (ui_printf):  Handle size_t_arg.
* ui-out.c (ui_out::vmessage): Likewise.
* unittests/format_pieces-selftests.c (test_format_int_sizes): New
function.
(run_tests): Call test_format_int_sizes.

gdb/gdbserver/ChangeLog:

* ax.c (ax_printf): Handle size_t_arg.

Change-Id: Ib6c44d88aa5bce265d757e4c0698881803dd186f

gdb/ChangeLog
gdb/gdbserver/ChangeLog
gdb/gdbserver/ax.c
gdb/gdbsupport/format.c
gdb/gdbsupport/format.h
gdb/printcmd.c
gdb/ui-out.c
gdb/unittests/format_pieces-selftests.c

index 44ace04beb905c5458f055e50524bb0dd430df87..4f40ea82ee9c4e3727a1a442eec3c81a6ecce64f 100644 (file)
@@ -1,3 +1,14 @@
+2019-11-12  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdbsupport/format.c (format_pieces::format_pieces): Support
+       printf 'z' size modifier.
+       * gdbsupport/format.h (enum argclass): Add size_t_arg.
+       * printcmd.c (ui_printf):  Handle size_t_arg.
+       * ui-out.c (ui_out::vmessage): Likewise.
+       * unittests/format_pieces-selftests.c (test_format_int_sizes): New
+       function.
+       (run_tests): Call test_format_int_sizes.
+
 2019-11-12  Christian Biesinger  <cbiesinger@google.com>
 
        * ada-exp.y (write_ambiguous_var): Update.
index 9d0afaaf28e61eb5ae46a7e559bb24ae905f22de..e17a7ca461e8b28ea11c77f242d3c24046ce775b 100644 (file)
@@ -1,3 +1,7 @@
+2019-11-12  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * ax.c (ax_printf): Handle size_t_arg.
+
 2019-11-06  Christian Biesinger  <cbiesinger@google.com>
 
        * linux-tdep.c (linux_info_proc): Use strtok_r instead of strtok.
index 2c096ef0cff200122ab8fd049d84aef4c4a699b2..21fde5e6926843a0f0ed0499cc5c352556bdc543 100644 (file)
@@ -904,6 +904,14 @@ ax_printf (CORE_ADDR fn, CORE_ADDR chan, const char *format,
            break;
          }
 
+       case size_t_arg:
+         {
+           size_t val = args[i];
+
+           printf (current_substring, val);
+           break;
+         }
+
        case literal_piece:
          /* Print a portion of the format string that has no
             directives.  Note that this will not include any
index 1e803501ae67ea965812149175e357b2bb1c22f2..2e2d90a92467ecda49cff7dd92e0526fa1dc9764 100644 (file)
@@ -123,6 +123,7 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions)
        int seen_space = 0, seen_plus = 0;
        int seen_big_l = 0, seen_h = 0, seen_big_h = 0;
        int seen_big_d = 0, seen_double_big_d = 0;
+       int seen_size_t = 0;
        int bad = 0;
        int n_int_args = 0;
 
@@ -234,6 +235,12 @@ 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')
+         {
+           seen_size_t = 1;
+           f++;
+         }
 
        switch (*f)
          {
@@ -251,7 +258,9 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions)
 
          case 'd':
          case 'i':
-           if (lcount == 0)
+           if (seen_size_t)
+             this_argclass = size_t_arg;
+           else if (lcount == 0)
              this_argclass = int_arg;
            else if (lcount == 1)
              this_argclass = long_arg;
index e2a47ba5187d951c91e318af4ea1224c5b5fecd2..07374db3910966764b3ecc3b83f63f5face7f5de 100644 (file)
@@ -38,7 +38,7 @@
 enum argclass
   {
     literal_piece,
-    int_arg, long_arg, long_long_arg, ptr_arg,
+    int_arg, long_arg, long_long_arg, size_t_arg, ptr_arg,
     string_arg, wide_string_arg, wide_char_arg,
     double_arg, long_double_arg,
     dec32float_arg, dec64float_arg, dec128float_arg
index 27aaf7a076a1e3c62b5aa095ffc662e755604ec9..323a5d05eb7aafc731d56cf4855c77b6333b0dd6 100644 (file)
@@ -2657,6 +2657,16 @@ ui_printf (const char *arg, struct ui_file *stream)
            {
              long val = value_as_long (val_args[i]);
 
+             DIAGNOSTIC_PUSH
+             DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+              fprintf_filtered (stream, current_substring, val);
+             DIAGNOSTIC_POP
+             break;
+           }
+         case size_t_arg:
+           {
+             size_t val = value_as_long (val_args[i]);
+
              DIAGNOSTIC_PUSH
              DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
               fprintf_filtered (stream, current_substring, val);
index 6b0b5acd3e1376cc3bfdbea357ae360074b58206..80845f4bcaa8d61ee3e7c202b645831a8b22e8da 100644 (file)
@@ -688,6 +688,24 @@ ui_out::vmessage (const ui_file_style &in_style, const char *format,
              }
          }
          break;
+       case size_t_arg:
+         {
+           size_t val = va_arg (args, size_t);
+           switch (piece.n_int_args)
+             {
+             case 0:
+               call_do_message (style, current_substring, val);
+               break;
+             case 1:
+               call_do_message (style, current_substring, intvals[0], val);
+               break;
+             case 2:
+               call_do_message (style, current_substring,
+                                intvals[0], intvals[1], val);
+               break;
+             }
+         }
+         break;
        case double_arg:
          call_do_message (style, current_substring, va_arg (args, double));
          break;
index ed83d9670fd1d36c33bb07497fb46e68fea94314..3971201478091d9c7e30a043a1f1637d66e75ea9 100644 (file)
@@ -76,12 +76,56 @@ test_gdb_formats ()
     }, true);
 }
 
+/* Test the different size modifiers that can be applied to an integer
+   argument.  Test with different integer format specifiers too.  */
+
+static void
+test_format_int_sizes ()
+{
+  check ("Hello\\t %hu%lu%llu%zu", /* ARI: %ll */
+    {
+      format_piece ("Hello\t ", literal_piece, 0),
+      format_piece ("%hu", int_arg, 0),
+      format_piece ("%lu", long_arg, 0),
+      format_piece ("%llu", long_long_arg, 0), /* ARI: %ll */
+      format_piece ("%zu", size_t_arg, 0)
+    });
+
+  check ("Hello\\t %hx%lx%llx%zx", /* ARI: %ll */
+    {
+      format_piece ("Hello\t ", literal_piece, 0),
+      format_piece ("%hx", int_arg, 0),
+      format_piece ("%lx", long_arg, 0),
+      format_piece ("%llx", long_long_arg, 0), /* ARI: %ll */
+      format_piece ("%zx", size_t_arg, 0)
+    });
+
+  check ("Hello\\t %ho%lo%llo%zo", /* ARI: %ll */
+    {
+      format_piece ("Hello\t ", literal_piece, 0),
+      format_piece ("%ho", int_arg, 0),
+      format_piece ("%lo", long_arg, 0),
+      format_piece ("%llo", long_long_arg, 0), /* ARI: %ll */
+      format_piece ("%zo", size_t_arg, 0)
+    });
+
+  check ("Hello\\t %hd%ld%lld%zd", /* ARI: %ll */
+    {
+      format_piece ("Hello\t ", literal_piece, 0),
+      format_piece ("%hd", int_arg, 0),
+      format_piece ("%ld", long_arg, 0),
+      format_piece ("%lld", long_long_arg, 0), /* ARI: %ll */
+      format_piece ("%zd", size_t_arg, 0)
+    });
+}
+
 static void
 run_tests ()
 {
   test_escape_sequences ();
   test_format_specifier ();
   test_gdb_formats ();
+  test_format_int_sizes ();
 }
 
 } /* namespace format_pieces */