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);
>>
next prev 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).