gas/ELF: Allow local symbol with hidden visibility
Commit Message
On Tue, Jun 23, 2026 at 10:22 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 23.06.2026 15:54, Michael Matz wrote:
> > On Tue, 23 Jun 2026, Jan Beulich wrote:
> >>> 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.
> >>
> >> IOW what you're suggesting as interpretation is that while STV_PROTECTED
> >> and STB_LOCAL may not combine, the visibility-wise more restricting
> >> STV_HIDDEN may combine with STB_LOCAL?
> >
> > Yes.
> >
> >> Make no sense to me, I'm afraid.
> >
> > That may be, and I agree that creating such situation willingly would
> > be suspect. But as we just saw, such combinations might be created
> > by an unlucky reality.
>
> Because of shortcomings in the tools used. I bet if there had been a
> warning, the approach chosen would have been a different one. (The
> approach chosen also isn't portable to non-ELF targets.)
>
> > And again: binding and visiblity are _orthogonal_.
> > One is for link-editing, the other for runtime linking. In principle all
> > combinations are "okay" (if questionable), and have obvious
> > implementations. But it's only that specific combination
> > STB_LOCAL+STV_PROTECTED that is explicitely made ill-formed in the spec
> > (despite it being also obviously implementable). So, sure, warning on
> > that combination can be done on the grounds of following the spec. But no
> > other combination is so spelled out, so there's no basis for trying to
> > disallow them.
>
> As with many things in specs, what's spelled out and what's implied
> is a matter of interpretation. As I think follows from earlier replies,
> I can see that there is room for interpretation here, and hence mine
> may not match what was intended. Yet we won't know for any other
> interpretation either, seeing the state the ELF spec is in.
>
> If others are in favor of following your interpretation, then I'm not
> going to stand in the way. But as of now it's not going to be me to
> make a patch to that effect. I simply couldn't write a description
> for it in good faith.
>
> >> (And would also make the implementation harder.)
> >
> > If a warning is too costly to implement, then it shouldn't be there.
> > Though it seems surprising that checking for "is_local && is_protected"
> > should be materially more difficult than for "is_local && !is_default_vis".
> > (I haven't looked at the concrete patch, though).
>
> Well, you may be right and it's not really more complex.
>
> Jan
Here is the patch.
Comments
On 24.06.2026 02:23, H.J. Lu wrote:
> On Tue, Jun 23, 2026 at 10:22 PM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 23.06.2026 15:54, Michael Matz wrote:
>>> On Tue, 23 Jun 2026, Jan Beulich wrote:
>>>>> 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.
>>>>
>>>> IOW what you're suggesting as interpretation is that while STV_PROTECTED
>>>> and STB_LOCAL may not combine, the visibility-wise more restricting
>>>> STV_HIDDEN may combine with STB_LOCAL?
>>>
>>> Yes.
>>>
>>>> Make no sense to me, I'm afraid.
>>>
>>> That may be, and I agree that creating such situation willingly would
>>> be suspect. But as we just saw, such combinations might be created
>>> by an unlucky reality.
>>
>> Because of shortcomings in the tools used. I bet if there had been a
>> warning, the approach chosen would have been a different one. (The
>> approach chosen also isn't portable to non-ELF targets.)
>>
>>> And again: binding and visiblity are _orthogonal_.
>>> One is for link-editing, the other for runtime linking. In principle all
>>> combinations are "okay" (if questionable), and have obvious
>>> implementations. But it's only that specific combination
>>> STB_LOCAL+STV_PROTECTED that is explicitely made ill-formed in the spec
>>> (despite it being also obviously implementable). So, sure, warning on
>>> that combination can be done on the grounds of following the spec. But no
>>> other combination is so spelled out, so there's no basis for trying to
>>> disallow them.
>>
>> As with many things in specs, what's spelled out and what's implied
>> is a matter of interpretation. As I think follows from earlier replies,
>> I can see that there is room for interpretation here, and hence mine
>> may not match what was intended. Yet we won't know for any other
>> interpretation either, seeing the state the ELF spec is in.
>>
>> If others are in favor of following your interpretation, then I'm not
>> going to stand in the way. But as of now it's not going to be me to
>> make a patch to that effect. I simply couldn't write a description
>> for it in good faith.
>>
>>>> (And would also make the implementation harder.)
>>>
>>> If a warning is too costly to implement, then it shouldn't be there.
>>> Though it seems surprising that checking for "is_local && is_protected"
>>> should be materially more difficult than for "is_local && !is_default_vis".
>>> (I haven't looked at the concrete patch, though).
>>
>> Well, you may be right and it's not really more complex.
>>
>> Jan
>
> Here is the patch.
The "& ~STV_HIDDEN" is clearly bogus there. If we follow that alternative
interpretation of the spec, no warning should be issued for STV_INTERNAL
either. I'm also surprised you don't undo more of the respective testsuite
changes then (i.e. about everywhere I had added .global to avoid the
warning).
Jan
From 0ea93af841c0f51371405bdce42755fef1dba9fb Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 24 Jun 2026 08:09:56 +0800
Subject: [PATCH] gas/ELF: Allow local symbol with hidden visibility
In the source code extracted from glibc:
extern void _dl_sysinfo_int80 (void)
__attribute__ ((visibility ("hidden")));
asm (".text\n\t"
".type _dl_sysinfo_int80,@function\n"
"_dl_sysinfo_int80:\n\t"
"int $0x80;\n\t"
"ret");
uintptr_t
foo ()
{
return (uintptr_t) _dl_sysinfo_int80;
}
_dl_sysinfo_int80 is a local function, but it is defined in an asm
statement. Since it is referenced in C, it is declared as hidden,
which leads to an assembler warning:
Warning: local symbol `_dl_sysinfo_int80' has non-default visibility
Symbol binding and visiblity are orthogonal. One is for link-editing,
the other for runtime linking. In principle, all combinations are "okay"
(if questionable), and have obvious implementations. But it's only that
specific combination STB_LOCAL+STV_PROTECTED that is explicitely made
ill-formed in the spec (despite it being also obviously implementable).
Warning on that combination can be done on the grounds of following the
spec. But no other combination is so spelled out, so there's no basis
for trying to disallow them.
Update elf_adjust_symtab to avoid such warning.
binutils/
PR gas/34312
* testsuite/binutils-all/localize-hidden-1.l: Adjusted.
gas/
PR gas/34312
* config/obj-elf.c (elf_adjust_symtab): Allow local symbol with
hidden visibility.
* testsuite/gas/elf/visibility.l: Adjusted.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
binutils/testsuite/binutils-all/localize-hidden-1.l | 1 -
gas/config/obj-elf.c | 5 ++++-
gas/testsuite/gas/elf/visibility.l | 1 -
3 files changed, 4 insertions(+), 3 deletions(-)
@@ -1,4 +1,3 @@
[^:]*: Assembler messages:
-[^:]*: Warning: local symbol .Lhidden. has non-default visibility
[^:]*: Warning: local symbol .Linternal. has non-default visibility
[^:]*: Warning: local symbol .Lprotected. has non-default visibility
@@ -2756,7 +2756,10 @@ elf_adjust_symtab (void)
const asymbol *bfdsym = symbol_get_bfdsym (symp);
elf_symbol_type *elfsym = elf_symbol_from (bfdsym);
- if (ELF_ST_VISIBILITY (elfsym->internal_elf_sym.st_other)
+ /* Allow local symbol with hidden visibility:
+ https://sourceware.org/bugzilla/show_bug.cgi?id=34312 */
+ if ((ELF_ST_VISIBILITY (elfsym->internal_elf_sym.st_other)
+ & ~STV_HIDDEN) != 0
&& !(bfdsym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)))
as_warn (_("local symbol `%s' has non-default visibility"),
S_GET_NAME (symp));
@@ -4,5 +4,4 @@
[^:]*:21: Warning: visibility of .ge. is already .hidden.
[^:]*:26: Warning: visibility of .we. is already .hidden.
[^:]*: Warning: local symbol .li. has non-default visibility
-[^:]*: Warning: local symbol .lh. has non-default visibility
[^:]*: Warning: local symbol .lp. has non-default visibility
--
2.54.0