Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Guinevere Larsen <guinevere@redhat.com>
To: simon.marchi@polymtl.ca, gdb-patches@sourceware.org
Subject: Re: [PATCH] gdb, gdbsupport, gdbserver: add support for printf 't' length modifier
Date: Mon, 19 Jan 2026 14:29:30 -0300	[thread overview]
Message-ID: <f8fe6579-ea48-4bff-980f-e48e849b5373@redhat.com> (raw)
In-Reply-To: <20260112182407.622150-1-simon.marchi@polymtl.ca>

On 1/12/26 3:24 PM, simon.marchi@polymtl.ca wrote:
> From: Simon Marchi <simon.marchi@polymtl.ca>
>
> Tom de Vries reported [1] that a use of the `t` printf length modifier
> (used for ptrdiff_t) breaks "set debug dwarf-die 1":
>
>      +break -qualified main
>      Reading Reading compcomp unit at offset  unit at offset 0x00x39
>
>      Reading comp unit at offset 0x1a8
>      Reading comp unit at offset 0x1e9
>      Reading comp unit at offset 0x2c5
>      Reading comp unit at offset 0x2a2
>      Reading comp unit at offset 0x904
>      Unrecognized format specifier 't' in printf
>
> This use is in dwarf2/read.c:
>
>        gdb_printf (gdb_stdlog, "Read die from %s@0x%tx of %s:\n",
> 		  m_die_section->get_name (),
> 		  (begin_info_ptr - m_die_section->buffer),
> 		  bfd_get_filename (m_abfd));
>
> Add support for the `t` length modifier in format_pieces, which
> gdb_printf ultimately uses (through ui_out::vmessage).  Modify the three
> users of format_pieces: gdb's printf command, gdb's ui_out::vmessage
> function and gdbserver's ax_printf function.
>
> The implementation is mostly copied from what we do for size_t.
>
> Since format_pieces is also used to implement the printf command, this
> patch brings user-visible changes.  Before:
>
>      (gdb) printf "%td\n", -123
>      ❌️ Unrecognized format specifier 't' in printf
>
> After:
>
>      (gdb) printf "%td\n", -123
>      -123
>
> [1] https://inbox.sourceware.org/gdb-patches/d4ccce34-aad5-4e3d-8fc9-efb2fc11275c@suse.de/
>
> Change-Id: Ie9fce78f5f48082d8f8a9ca2847b5ae26acaa60d
> ---

This commit seems to have caused a regression. After this, when starting 
GDB without the quiet flag I get the following:

0x7ffc6b9bc520s
Copyright (C) 2026 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <0x7ffc6b9bc560s>
This is free software: you are free to change and redistribute it
There is NO WARRANTY, to the extent permitted by law.
Type "0x7ffc6b9bc5e0s" and "0x7ffc6b9bc5a0s" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "0x7ffc6b9bc620s" for configuration details.
For bug reporting instructions, please see:
0x7ffc6b9bc660s.

That is, anywhere where GDB would print a styled string, we seem to be 
printing a pointer address instead.

>   gdb/printcmd.c                          | 10 ++++++++++
>   gdb/testsuite/gdb.base/printcmds.c      |  6 ++++++
>   gdb/testsuite/gdb.base/printcmds.exp    |  4 ++++
>   gdb/ui-out.c                            | 18 ++++++++++++++++++
>   gdb/unittests/format_pieces-selftests.c | 12 ++++++++----
>   gdbserver/ax.cc                         |  8 ++++++++
>   gdbsupport/format.cc                    | 11 ++++++++++-
>   gdbsupport/format.h                     |  2 +-
>   8 files changed, 65 insertions(+), 6 deletions(-)
>
> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index 783b83615d02..7c97fc719926 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -2815,6 +2815,16 @@ ui_printf (const char *arg, struct ui_file *stream)
>   	    {
>   	      size_t val = value_as_long (val_args[i]);
>   
> +	      DIAGNOSTIC_PUSH
> +	      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
> +		gdb_printf (stream, current_substring, val);
> +	      DIAGNOSTIC_POP
> +	      break;
> +	    }
> +	  case ptrdiff_t_arg:
> +	    {
> +	      ptrdiff_t val = value_as_long (val_args[i]);
> +
>   	      DIAGNOSTIC_PUSH
>   	      DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
>   		gdb_printf (stream, current_substring, val);
> diff --git a/gdb/testsuite/gdb.base/printcmds.c b/gdb/testsuite/gdb.base/printcmds.c
> index 8445fcc1aa2a..82796932e1d3 100644
> --- a/gdb/testsuite/gdb.base/printcmds.c
> +++ b/gdb/testsuite/gdb.base/printcmds.c
> @@ -2,6 +2,8 @@
>      It is explicitly unsigned to avoid differences due to native characters
>      being either signed or unsigned. */
>   #include <stdlib.h>
> +#include <stddef.h>
> +
>   unsigned char ctable1[256] = {
>     0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
>     0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
> @@ -77,6 +79,10 @@ charptr teststring2 = "more contents";
>   
>   const char *teststring3 = "this is a longer test string that we can use";
>   
> +/* For testing printf with %z (size_t) and %t (ptrdiff_t) length modifiers.  */
> +size_t test_size = 1234;
> +ptrdiff_t test_ptrdiff = -5678;
> +
>   /* Test printing of a struct containing character arrays. */
>   
>   struct some_arrays {
> diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
> index bc100f93df9a..32a952f01a55 100644
> --- a/gdb/testsuite/gdb.base/printcmds.exp
> +++ b/gdb/testsuite/gdb.base/printcmds.exp
> @@ -908,6 +908,10 @@ proc test_printf {} {
>       # PR cli/14977.
>       gdb_test "printf \"%s\\n\", 0" "\\(null\\)"
>   
> +    # Test %z (size_t) and %t (ptrdiff_t) length modifiers.
> +    gdb_test "printf \"%zu\\n\", test_size" "1234"
> +    gdb_test "printf \"%td\\n\", test_ptrdiff" "-5678"
> +
>       with_max_value_size 20 {
>   	gdb_test {printf "%s", teststring3} \
>   	    "^printed string requires 45 bytes, which is more than max-value-size"
> diff --git a/gdb/ui-out.c b/gdb/ui-out.c
> index 4f20e6b93477..87874e22530f 100644
> --- a/gdb/ui-out.c
> +++ b/gdb/ui-out.c
> @@ -682,6 +682,24 @@ ui_out::vmessage (const ui_file_style &in_style, const char *format,
>   	      }
>   	  }
>   	  break;
> +	case ptrdiff_t_arg:
> +	  {
> +	    ptrdiff_t val = va_arg (args, ptrdiff_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;
> diff --git a/gdb/unittests/format_pieces-selftests.c b/gdb/unittests/format_pieces-selftests.c
> index af574ccc900f..c5f3cf74f1dc 100644
> --- a/gdb/unittests/format_pieces-selftests.c
> +++ b/gdb/unittests/format_pieces-selftests.c
> @@ -105,40 +105,44 @@ test_gdb_formats ()
>   static void
>   test_format_int_sizes ()
>   {
> -  check ("Hello\\t %hu%lu%llu%zu", /* ARI: %ll */
> +  check ("Hello\\t %hu%lu%llu%zu%tu", /* ARI: %ll */
>       {
>         {"Hello\t ", literal_piece, 0},
>         {"%hu", int_arg, 0},
>         {"%lu", long_arg, 0},
>         {"%" LL "u", long_long_arg, 0},
>         {"%zu", size_t_arg, 0},
> +      {"%tu", ptrdiff_t_arg, 0},
>       });
>   
> -  check ("Hello\\t %hx%lx%llx%zx", /* ARI: %ll */
> +  check ("Hello\\t %hx%lx%llx%zx%tx", /* ARI: %ll */
>       {
>         {"Hello\t ", literal_piece, 0},
>         {"%hx", int_arg, 0},
>         {"%lx", long_arg, 0},
>         {"%" LL "x", long_long_arg, 0},
>         {"%zx", size_t_arg, 0},
> +      {"%tx", ptrdiff_t_arg, 0},
>       });
>   
> -  check ("Hello\\t %ho%lo%llo%zo", /* ARI: %ll */
> +  check ("Hello\\t %ho%lo%llo%zo%to", /* ARI: %ll */
>       {
>         {"Hello\t ", literal_piece, 0},
>         {"%ho", int_arg, 0},
>         {"%lo", long_arg, 0},
>         {"%" LL "o", long_long_arg, 0},
>         {"%zo", size_t_arg, 0},
> +      {"%to", ptrdiff_t_arg, 0},
>       });
>   
> -  check ("Hello\\t %hd%ld%lld%zd", /* ARI: %ll */
> +  check ("Hello\\t %hd%ld%lld%zd%td", /* ARI: %ll */
>       {
>         {"Hello\t ", literal_piece, 0},
>         {"%hd", int_arg, 0},
>         {"%ld", long_arg, 0},
>         {"%" LL "d", long_long_arg, 0},
>         {"%zd", size_t_arg, 0},
> +      {"%td", ptrdiff_t_arg, 0},
>       });
>   }
>   
> diff --git a/gdbserver/ax.cc b/gdbserver/ax.cc
> index 44fcf3157291..4993bed2532c 100644
> --- a/gdbserver/ax.cc
> +++ b/gdbserver/ax.cc
> @@ -908,6 +908,14 @@ ax_printf (CORE_ADDR fn, CORE_ADDR chan, const char *format,
>   	    break;
>   	  }
>   
> +	case ptrdiff_t_arg:
> +	  {
> +	    ptrdiff_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
> diff --git a/gdbsupport/format.cc b/gdbsupport/format.cc
> index b515a95114e0..43995edf453e 100644
> --- a/gdbsupport/format.cc
> +++ b/gdbsupport/format.cc
> @@ -111,6 +111,7 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
>   	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 seen_ptrdiff_t = 0;
>   	int bad = 0;
>   	int n_int_args = 0;
>   	bool seen_i64 = false;
> @@ -224,6 +225,11 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
>   	    seen_size_t = 1;
>   	    f++;
>   	    break;
> +	  case 't':
> +	    /* For ptrdiff_t.  */
> +	    seen_ptrdiff_t = 1;
> +	    f++;
> +	    break;
>   	  case 'I':
>   	    /* Support the Windows '%I64' extension, because an
>   	       earlier call to format_pieces might have converted %lld
> @@ -257,6 +263,8 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
>   	  case 'i':
>   	    if (seen_size_t)
>   	      this_argclass = size_t_arg;
> +	    else if (seen_ptrdiff_t)
> +	      this_argclass = ptrdiff_t_arg;
>   	    else if (lcount == 0)
>   	      this_argclass = int_arg;
>   	    else if (lcount == 1)
> @@ -334,7 +342,8 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
>   
>   	    if (lcount > 1 || seen_h || seen_big_h || seen_big_h
>   		|| seen_big_d || seen_double_big_d || seen_size_t
> -		|| seen_prec || seen_zero || seen_space || seen_plus)
> +		|| seen_ptrdiff_t || seen_prec || seen_zero || seen_space
> +		|| seen_plus)
>   	      bad = 1;
>   
>   	    this_argclass = value_arg;
> diff --git a/gdbsupport/format.h b/gdbsupport/format.h
> index 91bcf1db55a6..ced10e46a716 100644
> --- a/gdbsupport/format.h
> +++ b/gdbsupport/format.h
> @@ -36,7 +36,7 @@
>   enum argclass
>     {
>       literal_piece,
> -    int_arg, long_arg, long_long_arg, size_t_arg, ptr_arg,
> +    int_arg, long_arg, long_long_arg, size_t_arg, ptrdiff_t_arg, ptr_arg,
>       string_arg, wide_string_arg, wide_char_arg,
>       double_arg, long_double_arg,
>       dec32float_arg, dec64float_arg, dec128float_arg,
>
> base-commit: b9517052ce5c1d87bfd7030bcbf90a98f63fddf6


-- 
Cheers,
Guinevere Larsen
It/she


  parent reply	other threads:[~2026-01-19 17:30 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-12 18:24 simon.marchi
2026-01-15 19:24 ` Tom Tromey
2026-01-15 19:36   ` Simon Marchi
2026-01-15 19:42     ` Tom Tromey
2026-01-19 17:29 ` Guinevere Larsen [this message]
2026-01-19 18:09   ` Simon Marchi
2026-01-20 12:29     ` Guinevere Larsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f8fe6579-ea48-4bff-980f-e48e849b5373@redhat.com \
    --to=guinevere@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=simon.marchi@polymtl.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox