From: Jan Beulich Date: Fri, 28 Nov 2025 08:48:18 +0000 (+0100) Subject: ld: support most modifiers for printf() like vfinfo() format specifiers X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46871224c49722d408428f1e2f050d4c8a52cc4b;p=thirdparty%2Fbinutils-gdb.git ld: support most modifiers for printf() like vfinfo() format specifiers Not doing so is pretty error prone: One needs to distinguish e.g. ->einfo() and alike invocations out of libbfd from _bfd_error_handler() ones. Omit support for * though for now, as that would be more intrusive to implement. Use this then to disambiguate x86'es ISA level diagnostic of unknown bits, where decimal vs hex isn't immediately clear. --- diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 215a1569e9d..24894193c86 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -4247,7 +4247,7 @@ report_isa_level (struct bfd_link_info *info, bfd *abfd, info->callbacks->einfo ("x86-64-v4"); break; default: - info->callbacks->einfo (_(""), bit); + info->callbacks->einfo (_(""), bit); break; } if (bitmask) diff --git a/ld/ldmisc.c b/ld/ldmisc.c index 3f305fa457e..38cc7ff3a28 100644 --- a/ld/ldmisc.c +++ b/ld/ldmisc.c @@ -37,6 +37,27 @@ #include "ldmain.h" #include "ldfile.h" +static size_t +count_modifiers (const char *scan) +{ + size_t mods = strspn (scan, "-+ #0"); + + while (scan[mods] != '0' && ISDIGIT (scan[mods])) + ++mods; + if (scan[mods] == '.') + ++mods; + while (scan[mods] != '0' && ISDIGIT (scan[mods])) + ++mods; + + return mods; +} + +static char * +make_cfmt (const char *fmt, int nr) +{ + return xasprintf ("%%%.*s", nr, fmt); +} + /* %% literal % %C clever filename:linenumber with function @@ -119,6 +140,9 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) scan += 2; } + /* Skip most modifiers that printf() permits. */ + scan += count_modifiers (scan); + arg_type = Bad; switch (*scan++) { @@ -217,6 +241,8 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) if (*fmt == '%') { + size_t mods; + fmt++; arg_no = arg_count; @@ -226,8 +252,14 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) fmt += 2; } + /* Record modifiers that printf() permits and that we support. */ + mods = count_modifiers (fmt); + fmt += mods; + switch (*fmt++) { + char *cfmt; + case '\0': --fmt; /* Fall through. */ @@ -514,56 +546,32 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) } fprintf (fp, "%s", name); } - else + else /* Native (host) void* pointer, like printf(). */ { - /* native (host) void* pointer, like printf */ - fprintf (fp, "%p", args[arg_no].p); + /* Fallthru */ + case 's': /* Arbitrary string, like printf(). */ + cfmt = make_cfmt (fmt - 1 - mods, mods + 1); + fprintf (fp, cfmt, args[arg_no].p); + free (cfmt); ++arg_count; } break; - case 's': - /* arbitrary string, like printf */ - fprintf (fp, "%s", (char *) args[arg_no].p); - ++arg_count; - break; - - case 'd': - /* integer, like printf */ - fprintf (fp, "%d", args[arg_no].i); - ++arg_count; - break; - - case 'u': - /* unsigned integer, like printf */ - fprintf (fp, "%u", args[arg_no].i); + case 'd': /* Integer, like printf(). */ + case 'u': /* Unsigned integer, like printf(). */ + case 'x': /* Unsigned integer, like printf(). */ + cfmt = make_cfmt (fmt - 1 - mods, mods + 1); + fprintf (fp, cfmt, args[arg_no].i); + free (cfmt); ++arg_count; break; - case 'x': - /* unsigned integer, like printf */ - fprintf (fp, "%x", args[arg_no].i); - ++arg_count; - break; - - case 'l': - if (*fmt == 'd') - { - fprintf (fp, "%ld", args[arg_no].l); - ++arg_count; - ++fmt; - break; - } - else if (*fmt == 'u') - { - fprintf (fp, "%lu", args[arg_no].l); - ++arg_count; - ++fmt; - break; - } - else if (*fmt == 'x') + case 'l': /* (Unsigned) long integer, like printf(). */ + if (*fmt == 'd' || *fmt == 'u' || *fmt == 'x') { - fprintf (fp, "%lx", args[arg_no].l); + cfmt = make_cfmt (fmt - 1 - mods, mods + 2); + fprintf (fp, cfmt, args[arg_no].l); + free (cfmt); ++arg_count; ++fmt; break; diff --git a/ld/testsuite/ld-x86-64/pr31868a.l b/ld/testsuite/ld-x86-64/pr31868a.l index 1244dfd1a57..26872bccce5 100644 --- a/ld/testsuite/ld-x86-64/pr31868a.l +++ b/ld/testsuite/ld-x86-64/pr31868a.l @@ -1,4 +1,4 @@ -tmpdir/pr31868a.o: x86 ISA needed: x86-64-baseline, x86-64-v3, , -tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, +tmpdir/pr31868a.o: x86 ISA needed: x86-64-baseline, x86-64-v3, , +tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, tmpdir/pr31868b.o: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3 -tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4, +tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4, diff --git a/ld/testsuite/ld-x86-64/pr31868b.l b/ld/testsuite/ld-x86-64/pr31868b.l index 1380befde48..3ccf03c1e3c 100644 --- a/ld/testsuite/ld-x86-64/pr31868b.l +++ b/ld/testsuite/ld-x86-64/pr31868b.l @@ -1,2 +1,2 @@ -tmpdir/pr31868a.o: x86 ISA needed: x86-64-baseline, x86-64-v3, , +tmpdir/pr31868a.o: x86 ISA needed: x86-64-baseline, x86-64-v3, , tmpdir/pr31868b.o: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3 diff --git a/ld/testsuite/ld-x86-64/pr31868c.l b/ld/testsuite/ld-x86-64/pr31868c.l index 7de0be6c2b1..65c390c5e16 100644 --- a/ld/testsuite/ld-x86-64/pr31868c.l +++ b/ld/testsuite/ld-x86-64/pr31868c.l @@ -1,2 +1,2 @@ -tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, -tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4, +tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, +tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4,