public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: Luis Machado <luis.machado@arm.com>,
	Jan Beulich <jbeulich@suse.com>,
	Binutils <binutils@sourceware.org>
Cc: Nick Clifton <nickc@redhat.com>,
	"ramana.radhakrishnan@arm.com" <ramana.radhakrishnan@arm.com>,
	Richard Earnshaw <rearnsha@arm.com>,
	Marcus Shawcroft <marcus.shawcroft@arm.com>,
	Alan Modra <amodra@gmail.com>,
	Peter Bergner <bergner@vnet.ibm.com>,
	Geoff Keating <geoffk@geoffk.org>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Andrew Waterman <andrew@sifive.com>,
	Jim Wilson <jim.wilson.gcc@gmail.com>,
	Nelson Chu <nelson@rivosinc.com>, "H.J. Lu" <hjl.tools@gmail.com>
Subject: Re: [PATCH v2 2/2] gas: re-work line number tracking for macros and their expansions
Date: Wed, 14 Dec 2022 16:00:20 +0000	[thread overview]
Message-ID: <87edt20ycr.fsf@redhat.com> (raw)
In-Reply-To: <bcab2d13-bd15-373d-0817-45b33cb27789@arm.com>

Luis Machado via Binutils <binutils@sourceware.org> writes:

> Hi,
>
> I'm not yet sure how, but this patch has broken at least one gdb test (gdb.asm/asm-source.exp) for aarch64-linux (Ubuntu 22.04 and 20.04).
>
> Could you please take a look at it? I can do some testing with the aarch64 machines if that's helpful.
>
> FAIL: gdb.asm/asm-source.exp: f at main
> FAIL: gdb.asm/asm-source.exp: n at main
> FAIL: gdb.asm/asm-source.exp: next over macro
> FAIL: gdb.asm/asm-source.exp: list
> FAIL: gdb.asm/asm-source.exp: f in foo2
> FAIL: gdb.asm/asm-source.exp: n in foo2
> FAIL: gdb.asm/asm-source.exp: bt ALL in foo2
> FAIL: gdb.asm/asm-source.exp: bt 2 in foo2
> FAIL: gdb.asm/asm-source.exp: bt 3 in foo3
> FAIL: gdb.asm/asm-source.exp: finish from foo3
> FAIL: gdb.asm/asm-source.exp: info source asmsrc2.s
> FAIL: gdb.asm/asm-source.exp: info line
> FAIL: gdb.asm/asm-source.exp: next over foo3
> FAIL: gdb.asm/asm-source.exp: return from foo2

Can confirm I'm seeing the same set of failures on x86-64 gdb when using
gas that includes this patch.

Thanks,
Andrew


>
>                  === gdb Summary ===
>
> # of expected passes            15
> # of unexpected failures        14
>
> On 12/9/22 10:52, Jan Beulich via Binutils wrote:
>> The PR gas/16908 workaround aimed at uniformly reporting line numbers
>> to reference macro invocation sites. As mentioned in a comment this may
>> be desirable for small macros, but often isn't for larger ones. As a
>> first step improve diagnostics to report both locations, while aiming at
>> leaving generated debug info unaltered.
>> 
>> Note that macro invocation context is lost for any diagnostics issued
>> only after all input was processed (or more generally for any use of
>> as_*_where(), as the functions can't know whether the passed in location
>> is related to [part of] the present stack of locations). To maintain the
>> intended workaround behavior for PR gas/16908, a new as_where() is
>> introduced to "look through" macro invocations, while the existing
>> as_where() is renamed (and used in only very few places for now). Down
>> the road as_where() will likely want to return a list of (file,line)
>> pairs.
>> ---
>> v2: Fully cover Arm testsuite.
>> ---
>> Omitting testsuite adjustments from the inline patch, for its sheer size;
>> please see the attachment for the full (compressed) patch.
>> ---
>> Adding
>> 
>>        if (subseg_text_p (now_seg))
>> 	dwarf2_emit_insn (0);
>> 
>> to try_macro() (alongside using as_where_top() in dwarf2_where()) would
>> get .debug_line contents into reasonable shape (expressing both macro
>> invocation site and macro definition location). But that's likely
>> insufficient: We may want / need to represent macros as inline
>> subprograms and their expansions as inlined subroutines. Which in turn
>> looks cumbersome especially with the relatively recently added recording
>> of functions (with which macro expansions then would better be
>> associated, when marked as such).
>> 
>> --- a/gas/as.h
>> +++ b/gas/as.h
>> @@ -437,6 +437,10 @@ typedef struct _pseudo_type pseudo_typeS
>>   #define PRINTF_WHERE_LIKE(FCN) \
>>     void FCN (const char *file, unsigned int line, const char *format, ...) \
>>       __attribute__ ((__format__ (__printf__, 3, 4)))
>> +#define PRINTF_INDENT_LIKE(FCN) \
>> +  void FCN (const char *file, unsigned int line, unsigned int indent, \
>> +	    const char *format, ...) \
>> +    __attribute__ ((__format__ (__printf__, 4, 5)))
>>   
>>   #else /* __GNUC__ < 2 || defined(VMS) */
>>   
>> @@ -444,6 +448,10 @@ typedef struct _pseudo_type pseudo_typeS
>>   #define PRINTF_WHERE_LIKE(FCN)	void FCN (const char *file, \
>>   					  unsigned int line, \
>>   					  const char *format, ...)
>> +#define PRINTF_INDENT_LIKE(FCN)	void FCN (const char *file, \
>> +					  unsigned int line, \
>> +					  unsigned int indent, \
>> +					  const char *format, ...)
>>   
>>   #endif /* __GNUC__ < 2 || defined(VMS) */
>>   
>> @@ -453,6 +461,7 @@ PRINTF_LIKE (as_tsktsk);
>>   PRINTF_LIKE (as_warn);
>>   PRINTF_WHERE_LIKE (as_bad_where);
>>   PRINTF_WHERE_LIKE (as_warn_where);
>> +PRINTF_INDENT_LIKE (as_info_where);
>>   
>>   void   as_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
>>   void   signal_init (void);
>> @@ -487,7 +496,9 @@ void   cond_finish_check (int);
>>   void   cond_exit_macro (int);
>>   int    seen_at_least_1_file (void);
>>   void   app_pop (char *);
>> +void   as_report_context (void);
>>   const char * as_where (unsigned int *);
>> +const char * as_where_top (unsigned int *);
>>   const char * as_where_physical (unsigned int *);
>>   void   bump_line_counters (void);
>>   void   do_scrub_begin (int);
>> --- a/gas/input-scrub.c
>> +++ b/gas/input-scrub.c
>> @@ -104,6 +104,9 @@ static const char *logical_input_file;
>>   static unsigned int physical_input_line;
>>   static unsigned int logical_input_line;
>>   
>> +/* Indicator whether the origin of an update was a .linefile directive. */
>> +static bool is_linefile;
>> +
>>   /* Struct used to save the state of the input handler during include files */
>>   struct input_save {
>>     char *              buffer_start;
>> @@ -115,6 +118,7 @@ struct input_save {
>>     const char *        logical_input_file;
>>     unsigned int        physical_input_line;
>>     unsigned int        logical_input_line;
>> +  bool                is_linefile;
>>     size_t              sb_index;
>>     sb                  from_sb;
>>     enum expansion      from_sb_expansion; /* Should we do a conditional check?  */
>> @@ -166,6 +170,7 @@ input_scrub_push (char *saved_position)
>>     saved->logical_input_file = logical_input_file;
>>     saved->physical_input_line = physical_input_line;
>>     saved->logical_input_line = logical_input_line;
>> +  saved->is_linefile = is_linefile;
>>     saved->sb_index = sb_index;
>>     saved->from_sb = from_sb;
>>     saved->from_sb_expansion = from_sb_expansion;
>> @@ -193,6 +198,7 @@ input_scrub_pop (struct input_save *save
>>     logical_input_file = saved->logical_input_file;
>>     physical_input_line = saved->physical_input_line;
>>     logical_input_line = saved->logical_input_line;
>> +  is_linefile = saved->is_linefile;
>>     sb_index = saved->sb_index;
>>     from_sb = saved->from_sb;
>>     from_sb_expansion = saved->from_sb_expansion;
>> @@ -267,8 +273,6 @@ input_scrub_include_sb (sb *from, char *
>>       as_fatal (_("macros nested too deeply"));
>>     ++macro_nest;
>>   
>> -  gas_assert (expansion < expanding_nested);
>> -
>>   #ifdef md_macro_start
>>     if (expansion == expanding_macro)
>>       {
>> @@ -283,8 +287,6 @@ input_scrub_include_sb (sb *from, char *
>>        expansion.  */
>>     newline = from->len >= 1 && from->ptr[0] != '\n';
>>     sb_build (&from_sb, from->len + newline + 2 * sizeof (".linefile") + 30);
>> -  if (expansion == expanding_repeat && from_sb_expansion >= expanding_macro)
>> -    expansion = expanding_nested;
>>     from_sb_expansion = expansion;
>>     if (newline)
>>       {
>> @@ -437,10 +439,7 @@ bump_line_counters (void)
>>     if (sb_index == (size_t) -1)
>>       ++physical_input_line;
>>   
>> -  /* PR gas/16908 workaround: Don't bump logical line numbers while
>> -     expanding macros, unless file (and maybe line; see as_where()) are
>> -     used inside the macro.  */
>> -  if (logical_input_line != -1u && from_sb_expansion < expanding_macro)
>> +  if (logical_input_line != -1u)
>>       ++logical_input_line;
>>   }
>>   \f
>> @@ -471,10 +470,6 @@ new_logical_line_flags (const char *fnam
>>       case 1 << 3:
>>         if (line_number < 0 || fname != NULL)
>>   	abort ();
>> -      /* PR gas/16908 workaround: Ignore updates when nested inside a macro
>> -	 expansion.  */
>> -      if (from_sb_expansion == expanding_nested)
>> -	return;
>>         if (next_saved_file == NULL)
>>   	fname = physical_input_file;
>>         else if (next_saved_file->logical_input_file)
>> @@ -486,6 +481,8 @@ new_logical_line_flags (const char *fnam
>>         abort ();
>>       }
>>   
>> +  is_linefile = flags != 1 && (flags != 0 || fname);
>> +
>>     if (line_number >= 0)
>>       logical_input_line = line_number;
>>     else if (line_number == -1 && fname && !*fname && (flags & (1 << 2)))
>> @@ -499,15 +496,6 @@ new_logical_line_flags (const char *fnam
>>         && (logical_input_file == NULL
>>   	  || filename_cmp (logical_input_file, fname)))
>>       logical_input_file = fname;
>> -
>> -  /* When encountering file or line changes inside a macro, arrange for
>> -     bump_line_counters() to henceforth increment the logical line number
>> -     again, just like it does when expanding repeats.  See as_where() for
>> -     why changing file or line alone doesn't alter expansion mode.  */
>> -  if (from_sb_expansion == expanding_macro
>> -      && logical_input_file != NULL
>> -      && logical_input_line != -1u)
>> -    from_sb_expansion = expanding_repeat;
>>   }
>>   
>>   void
>> @@ -516,6 +504,33 @@ new_logical_line (const char *fname, int
>>     new_logical_line_flags (fname, line_number, 0);
>>   }
>>   
>> +void
>> +as_report_context (void)
>> +{
>> +  const struct input_save *saved = next_saved_file;
>> +  enum expansion expansion = from_sb_expansion;
>> +  int indent = 1;
>> +
>> +  if (!macro_nest)
>> +    return;
>> +
>> +  do
>> +    {
>> +      if (expansion != expanding_macro)
>> +	/* Nothing.  */;
>> +      else if (saved->logical_input_file != NULL
>> +	       && saved->logical_input_line != -1u)
>> +	as_info_where (saved->logical_input_file, saved->logical_input_line,
>> +		       indent, _("macro invoked from here"));
>> +      else
>> +	as_info_where (saved->physical_input_file, saved->physical_input_line,
>> +		       indent, _("macro invoked from here"));
>> +
>> +      expansion = saved->from_sb_expansion;
>> +      ++indent;
>> +    }
>> +  while ((saved = saved->next_saved_file) != NULL);
>> +}
>>   \f
>>   /* Return the current physical input file name and line number, if known  */
>>   
>> @@ -534,11 +549,53 @@ as_where_physical (unsigned int *linep)
>>     return NULL;
>>   }
>>   
>> -/* Return the current file name and line number.  */
>> +/* Return the file name and line number at the top most macro
>> +   invocation, unless .file / .line were used inside a macro.  */
>>   
>>   const char *
>>   as_where (unsigned int *linep)
>>   {
>> +  const char *file = as_where_top (linep);
>> +
>> +  if (macro_nest && is_linefile)
>> +    {
>> +      const struct input_save *saved = next_saved_file;
>> +      enum expansion expansion = from_sb_expansion;
>> +
>> +      do
>> +	{
>> +	  if (!saved->is_linefile)
>> +	    break;
>> +
>> +	  if (expansion != expanding_macro)
>> +	    /* Nothing.  */;
>> +	  else if (saved->logical_input_file != NULL
>> +		   && (linep == NULL || saved->logical_input_line != -1u))
>> +	    {
>> +	      if (linep != NULL)
>> +		*linep = saved->logical_input_line;
>> +	      file = saved->logical_input_file;
>> +	    }
>> +	  else if (saved->physical_input_file != NULL)
>> +	    {
>> +	      if (linep != NULL)
>> +		*linep = saved->physical_input_line;
>> +	      file = saved->physical_input_file;
>> +	    }
>> +
>> +	  expansion = saved->from_sb_expansion;
>> +	}
>> +      while ((saved = saved->next_saved_file) != NULL);
>> +    }
>> +
>> +  return file;
>> +}
>> +
>> +/* Return the current file name and line number.  */
>> +
>> +const char *
>> +as_where_top (unsigned int *linep)
>> +{
>>     if (logical_input_file != NULL
>>         && (linep == NULL || logical_input_line != -1u))
>>       {
>> @@ -549,4 +606,3 @@ as_where (unsigned int *linep)
>>   
>>     return as_where_physical (linep);
>>   }
>> -
>> --- a/gas/macro.c
>> +++ b/gas/macro.c
>> @@ -131,23 +131,21 @@ buffer_and_nest (const char *from, const
>>     else
>>       from_len = strlen (from);
>>   
>> -  /* Except for macros record the present source position, such that
>> -     diagnostics and debug info will be properly associated with the
>> -     respective original lines, rather than with the line of the ending
>> -     directive (TO).  */
>> -  if (from == NULL || strcasecmp (from, "MACRO") != 0)
>> -    {
>> -      unsigned int line;
>> -      char *linefile;
>> -
>> -      as_where (&line);
>> -      if (!flag_m68k_mri)
>> -	linefile = xasprintf ("\t.linefile %u .", line + 1);
>> -      else
>> -	linefile = xasprintf ("\tlinefile %u .", line + 1);
>> -      sb_add_string (ptr, linefile);
>> -      xfree (linefile);
>> -    }
>> +  /* Record the present source position, such that diagnostics and debug info
>> +     can be properly associated with the respective original lines, rather
>> +     than with the line of the ending directive (TO).  */
>> +  {
>> +    unsigned int line;
>> +    char *linefile;
>> +
>> +    as_where_top (&line);
>> +    if (!flag_m68k_mri)
>> +      linefile = xasprintf ("\t.linefile %u .", line + 1);
>> +    else
>> +      linefile = xasprintf ("\tlinefile %u .", line + 1);
>> +    sb_add_string (ptr, linefile);
>> +    xfree (linefile);
>> +  }
>>   
>>     while (more)
>>       {
>> @@ -249,14 +247,8 @@ buffer_and_nest (const char *from, const
>>   	    }
>>   
>>   	  /* PR gas/16908
>> -	     Apply and discard .linefile directives that appear within
>> -	     the macro.  For long macros, one might want to report the
>> -	     line number information associated with the lines within
>> -	     the macro definition, but we would need more infrastructure
>> -	     to make that happen correctly (e.g. resetting the line
>> -	     number when expanding the macro), and since for short
>> -	     macros we clearly prefer reporting the point of expansion
>> -	     anyway, there's not an obviously better fix here.  */
>> +	     Apply .linefile directives that appear within the macro, alongside
>> +	     keeping them for later expansion of the macro.  */
>>   	  if (from != NULL && strcasecmp (from, "MACRO") == 0
>>   	      && len >= 8 && strncasecmp (ptr->ptr + i, "linefile", 8) == 0)
>>   	    {
>> @@ -267,7 +259,6 @@ buffer_and_nest (const char *from, const
>>   	      s_linefile (0);
>>   	      restore_ilp ();
>>   	      ptr->ptr[ptr->len] = saved_eol_char;
>> -	      ptr->len = line_start;
>>   	    }
>>   	}
>>   
>> --- a/gas/messages.c
>> +++ b/gas/messages.c
>> @@ -18,6 +18,7 @@
>>      02110-1301, USA.  */
>>   
>>   #include "as.h"
>> +#include <limits.h>
>>   #include <signal.h>
>>   
>>   /* If the system doesn't provide strsignal, we get it defined in
>> @@ -119,7 +120,7 @@ as_show_where (void)
>>     const char *file;
>>     unsigned int line;
>>   
>> -  file = as_where (&line);
>> +  file = as_where_top (&line);
>>     identify (file);
>>     if (file)
>>       {
>> @@ -130,6 +131,25 @@ as_show_where (void)
>>       }
>>   }
>>   
>> +/* Send to stderr a string as information, with location data passed in.
>> +   Note that for now this is not intended for general use.  */
>> +
>> +void
>> +as_info_where (const char *file, unsigned int line, unsigned int indent,
>> +	       const char *format, ...)
>> +{
>> +  va_list args;
>> +  char buffer[2000];
>> +
>> +  gas_assert (file != NULL && line > 0 && indent <= INT_MAX);
>> +
>> +  va_start (args, format);
>> +  vsnprintf (buffer, sizeof (buffer), format, args);
>> +  va_end (args);
>> +  fprintf (stderr, "%s:%u: %*s%s%s\n",
>> +	   file, line, (int)indent, "", _("Info: "), buffer);
>> +}
>> +
>>   /* Send to stderr a string as a warning, and locate warning
>>      in input file(s).
>>      Please only use this for when we have some recovery action.
>> @@ -146,6 +166,7 @@ as_tsktsk (const char *format, ...)
>>     vfprintf (stderr, format, args);
>>     va_end (args);
>>     (void) putc ('\n', stderr);
>> +  as_report_context ();
>>   }
>>   
>>   /* The common portion of as_warn and as_warn_where.  */
>> @@ -153,10 +174,15 @@ as_tsktsk (const char *format, ...)
>>   static void
>>   as_warn_internal (const char *file, unsigned int line, char *buffer)
>>   {
>> +  bool context = false;
>> +
>>     ++warning_count;
>>   
>>     if (file == NULL)
>> -    file = as_where (&line);
>> +    {
>> +      file = as_where_top (&line);
>> +      context = true;
>> +    }
>>   
>>     identify (file);
>>     if (file)
>> @@ -168,6 +194,10 @@ as_warn_internal (const char *file, unsi
>>       }
>>     else
>>       fprintf (stderr, "%s%s\n", _("Warning: "), buffer);
>> +
>> +  if (context)
>> +    as_report_context ();
>> +
>>   #ifndef NO_LISTING
>>     listing_warning (buffer);
>>   #endif
>> @@ -194,7 +224,7 @@ as_warn (const char *format, ...)
>>       }
>>   }
>>   
>> -/* Like as_bad but the file name and line number are passed in.
>> +/* Like as_warn but the file name and line number are passed in.
>>      Unfortunately, we have to repeat the function in order to handle
>>      the varargs correctly and portably.  */
>>   
>> @@ -218,10 +248,15 @@ as_warn_where (const char *file, unsigne
>>   static void
>>   as_bad_internal (const char *file, unsigned int line, char *buffer)
>>   {
>> +  bool context = false;
>> +
>>     ++error_count;
>>   
>>     if (file == NULL)
>> -    file = as_where (&line);
>> +    {
>> +      file = as_where_top (&line);
>> +      context = true;
>> +    }
>>   
>>     identify (file);
>>     if (file)
>> @@ -233,6 +268,10 @@ as_bad_internal (const char *file, unsig
>>       }
>>     else
>>       fprintf (stderr, "%s%s\n", _("Error: "), buffer);
>> +
>> +  if (context)
>> +    as_report_context ();
>> +
>>   #ifndef NO_LISTING
>>     listing_error (buffer);
>>   #endif
>> @@ -290,6 +329,7 @@ as_fatal (const char *format, ...)
>>     vfprintf (stderr, format, args);
>>     (void) putc ('\n', stderr);
>>     va_end (args);
>> +  as_report_context ();
>>     /* Delete the output file, if it exists.  This will prevent make from
>>        thinking that a file was created and hence does not need rebuilding.  */
>>     if (out_file_name != NULL)
>> @@ -312,6 +352,7 @@ as_abort (const char *file, int line, co
>>       fprintf (stderr, _("Internal error in %s at %s:%d.\n"), fn, file, line);
>>     else
>>       fprintf (stderr, _("Internal error at %s:%d.\n"), file, line);
>> +  as_report_context ();
>>   
>>     fprintf (stderr, _("Please report this bug.\n"));
>>   
>> --- a/gas/sb.h
>> +++ b/gas/sb.h
>> @@ -66,11 +66,9 @@ extern size_t sb_skip_comma (size_t, sb
>>   
>>   /* Actually in input-scrub.c.  */
>>   enum expansion {
>> -  /* Note: Order matters!  */
>>     expanding_none,
>>     expanding_repeat,
>>     expanding_macro,
>> -  expanding_nested, /* Only for internal use of input-scrub.c.  */
>>   };
>>   extern void input_scrub_include_sb (sb *, char *, enum expansion);
>>   


  parent reply	other threads:[~2022-12-14 16:00 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-09 10:47 [PATCH v2 0/2] gas: diagnostic improvements for macros Jan Beulich
2022-12-09 10:49 ` [PATCH v2 1/2] Arm: avoid unhelpful uses of .macro in testsuite Jan Beulich
2022-12-09 10:52 ` [PATCH v2 2/2] gas: re-work line number tracking for macros and their expansions Jan Beulich
2022-12-14 14:03   ` Luis Machado
2022-12-14 14:13     ` Luis Machado
2022-12-14 16:00     ` Andrew Burgess [this message]
2022-12-14 16:58       ` Andrew Burgess
2022-12-15  8:28         ` Jan Beulich
2022-12-15 10:50         ` Jan Beulich
2022-12-15 17:00           ` Andrew Burgess

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=87edt20ycr.fsf@redhat.com \
    --to=aburgess@redhat.com \
    --cc=amodra@gmail.com \
    --cc=andrew@sifive.com \
    --cc=bergner@vnet.ibm.com \
    --cc=binutils@sourceware.org \
    --cc=geoffk@geoffk.org \
    --cc=hjl.tools@gmail.com \
    --cc=jbeulich@suse.com \
    --cc=jim.wilson.gcc@gmail.com \
    --cc=luis.machado@arm.com \
    --cc=marcus.shawcroft@arm.com \
    --cc=nelson@rivosinc.com \
    --cc=nickc@redhat.com \
    --cc=palmer@dabbelt.com \
    --cc=ramana.radhakrishnan@arm.com \
    --cc=rearnsha@arm.com \
    /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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).