From: Matthieu Longo Date: Thu, 22 Jan 2026 17:34:39 +0000 (+0000) Subject: ld: bring vfinfo() in parity with printf() for format specifiers ll[d|i|x] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ba5d7518a79eaf1d3e2774f179697c30faca23a1;p=thirdparty%2Fbinutils-gdb.git ld: bring vfinfo() in parity with printf() for format specifiers ll[d|i|x] vfinfo() does not currently support the double-'l' ('ll') length modifier for 'd', 'u', and 'x' conversion specifiers. This caused incorrect behavior when using PRI[d|u|x][32|64] on some platforms, and is error-prone for developers who reasonably expect printf-compatible semantics. This patch adds support for ll[d|u|x] to align vfinfo() with printf() and improve portability and robustness. --- diff --git a/ld/ldmisc.c b/ld/ldmisc.c index 8668e55f06d..3deceb76719 100644 --- a/ld/ldmisc.c +++ b/ld/ldmisc.c @@ -98,6 +98,7 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) { int i; long l; + long long ll; void *p; bfd_vma v; struct { @@ -110,6 +111,7 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) Bad, Int, Long, + LongLong, Ptr, Vma, RelAddr @@ -181,10 +183,16 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) break; case 'l': + bool ll_type = false; + if (*scan == 'l') + { + ll_type = true; + ++scan; + } if (*scan == 'd' || *scan == 'u' || *scan == 'x') { ++scan; - arg_type = Long; + arg_type = (ll_type ? LongLong : Long); } break; @@ -211,6 +219,9 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) case Long: args[arg_no].l = va_arg (ap, long); break; + case LongLong: + args[arg_no].ll = va_arg (ap, long long); + break; case Ptr: args[arg_no].p = va_arg (ap, void *); break; @@ -566,11 +577,21 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning) ++arg_count; break; - case 'l': /* (Unsigned) long integer, like printf(). */ + case 'l': /* (Unsigned) (long) long integer, like printf(). */ + bool ll_type = false; + if (*fmt == 'l') + { + fmt++; + ll_type = true; + } if (*fmt == 'd' || *fmt == 'u' || *fmt == 'x') { - cfmt = make_cfmt (fmt - 1 - mods, mods + 2); - fprintf (fp, cfmt, args[arg_no].l); + unsigned int mods_len = (ll_type ? 2 : 1); + cfmt = make_cfmt (fmt - mods_len - mods, mods + mods_len + 1); + if (ll_type) + fprintf (fp, cfmt, args[arg_no].ll); + else + fprintf (fp, cfmt, args[arg_no].l); free (cfmt); ++arg_count; ++fmt;