[PATCH v1] ld: bring vfinfo() in parity with printf() for format specifiers ll[d|i|x]

Matthieu Longo matthieu.longo@arm.com
Thu Jan 22 17:51:46 GMT 2026


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.
---
 ld/ldmisc.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/ld/ldmisc.c b/ld/ldmisc.c
index 8668e55f06d..f74216658cf 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;
@@ -567,10 +578,20 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning)
 	      break;
 
 	    case 'l': /* (Unsigned) 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;
-- 
2.52.0



More information about the Binutils mailing list