[PATCH v3] elf: Don't set its DT_VERSYM entry for unversioned symbol

Michael Matz matz@suse.de
Thu Nov 13 14:19:17 GMT 2025


Hello,

On Thu, 13 Nov 2025, H.J. Lu wrote:

> > > > Two values are reserved:
> > > >
> > > >   VER_NDX_LOCAL  0 - The symbol is private, and is not available
> > > > outside this object.
> > >
> > > Doesn't this mean that the mold behaviour is correct?
> >
> > I agree.  That numeric value '1' (instead of '0') is the default value (as
> > the version to use when nothing particularly interesting is specified) is
> > a wart, but one that we now need to follow.  If version info must be
> > encoded then a global undefined symbol without a version requirement has
> > to continue using value 1.
> >
> > > $ binutils/readelf -WDsV c.so
> > >
> > > Symbol table for image contains 9 entries:
> > >    Num:    Value          Size Type    Bind   Vis      Ndx Name
> > >      0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
> > >      1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
> > >      2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)
> > >      3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
> > >      4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
> > >      5: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)
> > >      6: 0000000000004010    56 OBJECT  GLOBAL DEFAULT   21 ext_var
> > >      7: 000000000000112a    43 FUNC    GLOBAL DEFAULT   12 print
> > >      8: 0000000000001155    46 FUNC    GLOBAL DEFAULT   12 print64
> > >
> > > Version symbols section '.gnu.version' contains 9 entries:
> > >  Addr: 0x0000000000000390  Offset: 0x00000390  Link: 3 (.dynsym)
> > >   000:   0 (*local*)       0 (*local*)       2 (GLIBC_2.2.5)   0 (*local*)
> > >   004:   0 (*local*)       2 (GLIBC_2.2.5)   0 (*local*)       0 (*local*)
> > >   008:   0 (*local*)
> >
> > I also don't see justification for the WEAK undefined symbols to be
> > 'local' here.  IMO they all should be value 1.  If that means that we
> > can't differentiate between a symbol definition of 'foo' vs 'foo@'
> > (with empty version), then that's what we need to pay.  Alternatively an
> > explicitely empty version with a different value than 1 could be
> > introduced to record the difference, but that seems unhelpfully quirky.
> 
> VER_NDX_LOCAL (0) doesn't mean local visibility.  (*local*)  indicates 
> index 0
> 
> https://docs.oracle.com/en/operating-systems/solaris/oracle-solaris/11.4/linkers-libraries/version-symbol-section.html
> 
> has

These clarifications are "recent" additions, for some definition of 
recent.  Compare e.g. https://shrubbery.net/solaris9ab/SUNWdev/LLM/p45.html 

For reference, also see 
https://sourceware.org/bugzilla/show_bug.cgi?id=26002 where Alan fixed 
exactly such occurence (and it also refers to a hack added to gold to make 
it work with undefined syms that are NDX_LOCAL).  It's pretty clear that 
many people, including linker authors, assume that the very old (as in: 
having always existed) comment "Symbol has local scope." is the 
gospel, and don't know about any further clarifications.  Even if it 
weren't so:

> An undefined global symbol defined within an object that does not have
> a SHT_SUNW_verneed version dependency section. Or, an undefined global
> symbol defined within an object in which the version dependency
> section does not assign version indexes.

This point doesn't apply (the others trivially don't): we're talking about 
an object that _has_ a version section that assigns indices, and also has 
a verneed section.  [It seems to me that this (later introduced) allowance 
for NDX_LOCAL on undefined symbols is only there to clarify the confusion 
that might arise if there's no other sections that actually define what 
these version indices should mean.]

As an aside, even if the above point would apply and NDX_LOCAL _could_ 
be expected in this situation, then it still wouldn't be required to be 
NDX_LOCAL and hence: we're talking about an object file producer here, 
and those should be conservative in what they produce.  Using NDX_GLOBAL 
in this situation is the conservative choice.


Ciao,
Michael.


More information about the Binutils mailing list