[binutils-gdb] ld: support most modifiers for printf() like vfinfo() format specifiers
Jan Beulich
jbeulich@sourceware.org
Fri Nov 28 08:51:13 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=46871224c49722d408428f1e2f050d4c8a52cc4b
commit 46871224c49722d408428f1e2f050d4c8a52cc4b
Author: Jan Beulich <jbeulich@suse.com>
Date: Fri Nov 28 09:48:18 2025 +0100
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:
---
bfd/elfxx-x86.c | 2 +-
ld/ldmisc.c | 90 +++++++++++++++++++++------------------
ld/testsuite/ld-x86-64/pr31868a.l | 6 +--
ld/testsuite/ld-x86-64/pr31868b.l | 2 +-
ld/testsuite/ld-x86-64/pr31868c.l | 4 +-
5 files changed, 56 insertions(+), 48 deletions(-)
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 (_("<unknown: %x>"), bit);
+ info->callbacks->einfo (_("<unknown: %#x>"), 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, <unknown: 10>, <unknown: 20>
-tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, <unknown: 40>
+tmpdir/pr31868a.o: x86 ISA needed: x86-64-baseline, x86-64-v3, <unknown: 0x10>, <unknown: 0x20>
+tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, <unknown: 0x40>
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, <unknown: 10>
+tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4, <unknown: 0x10>
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, <unknown: 10>, <unknown: 20>
+tmpdir/pr31868a.o: x86 ISA needed: x86-64-baseline, x86-64-v3, <unknown: 0x10>, <unknown: 0x20>
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, <unknown: 40>
-tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4, <unknown: 10>
+tmpdir/pr31868a.o: x86 ISA used: x86-64-v3, x86-64-v4, <unknown: 0x40>
+tmpdir/pr31868b.o: x86 ISA used: x86-64-baseline, x86-64-v2, x86-64-v4, <unknown: 0x10>
More information about the Binutils-cvs
mailing list