[cfe-dev] different gcc/clang behavior for Internal visibility

Fangrui Song via cfe-dev cfe-dev at lists.llvm.org
Mon May 10 12:51:59 PDT 2021


On 2021-05-10, Y Song via cfe-dev wrote:
>Hi,
>
>The bpf linker project tries to explore to use INTERNAL visibility as in
>   https://lore.kernel.org/bpf/20210507054119.270888-1-andrii@kernel.org/
>
>But we found clang actually changed user "internal" visibility to "hidden".
>For example, I have the following example,
>
>$ cat t.c
>int __attribute__((visibility("internal"))) foo() { return 0; }
>$ clang -c t.c && llvm-readelf -s t.o | grep foo
>     3: 0000000000000000     8 FUNC    GLOBAL HIDDEN      2 foo
>$ gcc -c t.c && llvm-readelf -s t.o | grep foo
>     8: 0000000000000000    11 FUNC    GLOBAL INTERNAL    1 foo
>$
>
>Looks like this is caused by clang Attr.td,
>
>diff --git a/clang/include/clang/Basic/Attr.td
>b/clang/include/clang/Basic/Attr.td
>index 5e04f32187cd..4559a1bcfe42 100644
>--- a/clang/include/clang/Basic/Attr.td
>+++ b/clang/include/clang/Basic/Attr.td
>@@ -2776,7 +2776,7 @@ def Visibility : InheritableAttr {
>   let Spellings = [GCC<"visibility">];
>   let Args = [EnumArgument<"Visibility", "VisibilityType",
>                            ["default", "hidden", "internal", "protected"],
>-                           ["Default", "Hidden", "Hidden", "Protected"]>];
>+                           ["Default", "Hidden", "Internal", "Protected"]>];
>   let MeaningfulToClassTemplateDefinition = 1;
>   let Documentation = [Undocumented];
> }
>@@ -2786,7 +2786,7 @@ def TypeVisibility : InheritableAttr {
>   let Spellings = [Clang<"type_visibility">];
>   let Args = [EnumArgument<"Visibility", "VisibilityType",
>                            ["default", "hidden", "internal", "protected"],
>-                           ["Default", "Hidden", "Hidden", "Protected"]>];
>+                           ["Default", "Hidden", "Internal", "Protected"]>];
> //  let Subjects = [Tag, ObjCInterface, Namespace];
>   let Documentation = [Undocumented];
> }
>
>One of early commits,
>
>commit 570024a8d9b4a4aa4a35f077a0a65003dc7b71fe
>Author: Eli Friedman <eli.friedman at gmail.com>
>Date:   Thu Aug 5 06:57:20 2010 +0000
>
>    Implement #pragma GCC visibility.
>
>    llvm-svn: 110315
>
>I see
>
>+    else if (VisType->isStr("internal"))
>+      type = VisibilityAttr::HiddenVisibility; // FIXME
>
>Do we have any plan to support Internal visibility?

I don't think there is value supporting STV_INTERNAL.

STV_INTERNAL as we see today in the ELF specification was requested by SGI.

> The meaning of this visibility attribute may be defined by processor
> supplements to further constrain hidden symbols. A processor
> supplement's definition should be such that generic tools can safely
> treat internal symbols as hidden.  An internal symbol contained in a
> relocatable object must be either removed or converted to STB_LOCAL
> binding by the link-editor when the relocatable object is included in an
> executable file or shared object.

I recall from reading somewhere that it is used by its propritery
compiler for some LTO like optimizations. STV_INTERNAL is identical to
STV_HIDDEN in GNU/Solaris (and likely HP-UX).

For the Linux kernel, my suggestion is to just use __attribute__((visibility("hidden"))).
Then there will be no confusion that "internal" translates to STV_HIDDEN.


More information about the cfe-dev mailing list