This is an archive of the discontinued LLVM Phabricator instance.

[COFF] Don't generate -exclude-symbols for dllexported symbols
AbandonedPublic

Authored by mstorsjo on Sep 1 2022, 6:02 AM.

Details

Summary

A symbol can end up both with hidden visibility and a dllexport
attribute (in builds that set global flags like -fvisibility=hidden
or similar). In such cases, the hidden visibility doesn't have any
effect, as the dllexport directives take precedence, and no
autoexporting of all eligible symbols take place.

Therefore, it's entirely redundant to produce both -export: and
-exclude-symbols: for such a symbol - only produce export.

Even if an object file does contain one or more -export: directives,
it's relevant to include -exclude-symbols: for all other hidden
symbols though, because the linker could be invoked with
--export-all-symbols.

Diff Detail

Event Timeline

mstorsjo created this revision.Sep 1 2022, 6:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 1 2022, 6:02 AM
mstorsjo requested review of this revision.Sep 1 2022, 6:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 1 2022, 6:02 AM
rnk accepted this revision.Sep 1 2022, 10:35 AM

lgtm

This revision is now accepted and ready to land.Sep 1 2022, 10:35 AM
MaskRay added a comment.EditedSep 1 2022, 11:11 AM

This looks somewhat weird. How does a symbol end up with hidden dllexport? In other object file formats (ELF, Mach-O) this can't happen, since a hidden symbol cannot be exported.
In particular, in ELF, a STV_HIDDEN symbol's binding is changed to STB_LOCAL. Such a symbol cannot be a symbol resolution (relocation processing or dlsym) target. ld.lld never places a local symbol in the dynamic symbol table.

This looks somewhat weird. How does a symbol end up with hidden dllexport? In other object file formats (ELF, Mach-O) this can't happen, since a hidden symbol cannot be exported.

It can happen if you build with e.g. -fvisibility=hidden, coupled with source that have __declspec(dllexport) for the symbols that should be exported.

Consider a project that has been built with -fvisibility=hidden traditionally (which has had no effect at all on windows targets, up until a month ago). Such a project would have e.g. an EXPORT define for symbols that should be exported. For windows, it expands to __declspec(dllexport) while it expands to __attribute__((visibility(“default”))) on other OSes.

So in one sense, I guess one could say that dllexport should imply default visibility on the clang level too.

MaskRay added a comment.EditedSep 1 2022, 7:52 PM

This looks somewhat weird. How does a symbol end up with hidden dllexport? In other object file formats (ELF, Mach-O) this can't happen, since a hidden symbol cannot be exported.

It can happen if you build with e.g. -fvisibility=hidden, coupled with source that have __declspec(dllexport) for the symbols that should be exported.

Consider a project that has been built with -fvisibility=hidden traditionally (which has had no effect at all on windows targets, up until a month ago). Such a project would have e.g. an EXPORT define for symbols that should be exported. For windows, it expands to __declspec(dllexport) while it expands to __attribute__((visibility(“default”))) on other OSes.

So in one sense, I guess one could say that dllexport should imply default visibility on the clang level too.

Yes. I think this is better. __attribute__((visibility("hidden"))) __declspec(dllexport) should probably lead to an error.

Sent D133180 to suppress hidden for dllexport as we do for dllimport.

Yes. I think this is better.

Sent D133180 to suppress hidden for dllexport as we do for dllimport.

Thanks. What do you think about this patch then - I think it still might be best to do this change? E.g. if other frontends than clang generate such IR - even if it is a bit tautological.

__attribute__((visibility("hidden"))) __declspec(dllexport) should probably lead to an error.

Should, but doesn't yet - how hard do you think it'd be to add checking for that?

Yes. I think this is better.

Sent D133180 to suppress hidden for dllexport as we do for dllimport.

Thanks. What do you think about this patch then - I think it still might be best to do this change? E.g. if other frontends than clang generate such IR - even if it is a bit tautological.

__attribute__((visibility("hidden"))) __declspec(dllexport) should probably lead to an error.

Should, but doesn't yet - how hard do you think it'd be to add checking for that?

Not too difficult:) I have read a bit the visibility code. Created D133266 to reject the construct in Clang and D133267 to reject hidden dllexport IR (note that we already reject hidden dllimport IR).

mstorsjo abandoned this revision.Sep 5 2022, 12:51 PM

Superseded by D133180, D133266 and D133267 - thanks @MaskRay!