[PATCH 2/3] gas/ELF: warn upon non-default visibility of local symbols

Michael Matz matz@suse.de
Tue Jun 23 13:14:46 GMT 2026


Hello,

On Tue, 23 Jun 2026, Jan Beulich wrote:

> ... this actual reference, arguably the compiler should also emit a .global
> directive. It generally gets away without doing so because referenced symbols
> which aren't otherwise defined are implicitly global (which, seeing how
> other assemblers behave, can be argued as being a bug, but apparently is
> "traditional behavior" on UNIXes).

An assembler isn't a structured programming language environment, I think 
the quotes are undeserved: its entirely sensible that an assembler that 
sees a symbol reference for a symbol that at file-end is still undefined 
assumes that such symbol then obviously must come from a different file 
and hence be global (binding).

> > ELF spec
> > doesn't forbid the hidden visibility on a local symbol.  It is just a no-op.
> 
> You did read
> 
> "The spec explicitly precludes STB_LOCAL together with STV_PROTECTED (and,
>  implicity, STV_HIDDEN or STV_INTERNAL), so we better wouldn't entirely
>  silently write out symbols violating this."
> 
> in the patch description, didn't you? If you think that's wrong, did you
> then not consider going back to the ELF spec to find what exactly is said
> there: "A symbol with STB_LOCAL binding may not have STV_PROTECTED
> visibility." And then for STV_HIDDEN: "Such a symbol is necessarily
> protected." I.e. what is said for STV_PROTECTED applies to STV_HIDDEN (and
> STV_INTERNAL) as well, at least according to my interpretation of that
> wording.

I think that's a misinterpretation.  "a symbol is protected" is different 
from "a symbol has STV_PROTECTED visibility".  The former is defined in 
the section for the latter: 

  A symbol defined in the current component is protected if it is visible 
  in other components but cannot be preempted. Any reference to such a 
  symbol from within the defining component must be resolved to the 
  definition in that component, even if there is a definition in another 
  component that would interpose by the default rules. A symbol with 
  STB_LOCAL binding will not have STV_PROTECTED visibility.

and _that definition_ is invoked by STV_HIDDEN:

  A symbol defined in the current component is hidden if its name is not 
  visible to other components. Such a symbol is necessarily protected.

IMHO it's clear that a symbol hence "can be protected" without having its 
visibility be STV_PROTECTED.  Namely when it is STV_HIDDEN: its then 
protected _and_ hidden (which is of course redundant, because hidden 
implies protected, but as we are word-smithing, lets be precise).

That a STB_LOCAL symbol cannot have STV_PROTECTED visibility doesn't 
transfer to STV_HIDDEN from this wording, and from nothing else either, 
conceptually binding and visibility are orthogonal concepts and this 
specific disallowance for the STB_LOCAL+STV_PROTECTED combination is ... 
well, specific.  That is the wart, not that STB_LOCAL+STV_HIDDEN was 
"forgotten" to be disallowed.


Ciao,
Michael.


More information about the Binutils mailing list