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

Matthieu Longo matthieu.longo@arm.com
Fri Jan 23 10:44:20 GMT 2026


On 23/01/2026 08:55, Jan Beulich wrote:
> On 22.01.2026 18:51, Matthieu Longo wrote:
>> 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.
> 
> Okay with ...
> 
>> --- 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().  */
> 
> ... this comment also adjusted, to e.g.
> 
> 	    case 'l': /* (Unsigned) (long) long integer, like printf().  */
> 

Fixed and merged.

> Just to mention, since you weren't explicitly Cc-ed: Did you see Alan's report
> from earlier this morning?
> 
> Jan
> 

Do you mean "object attributes v2 test woes" ?

Matthieu

>> +	      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;
> 



More information about the Binutils mailing list