This matches the equivalent flag implemented in GNU linkers, see
https://sourceware.org/pipermail/binutils/2020-June/111685.html for
the associated discussion.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
I'm open to other suggestions for the option name, other thing we considered is -start-stop-symbols-visibility=....
-z hide-start-stop maybe? (to shorten the name a bit)
lld/ELF/Writer.cpp | ||
---|---|---|
2231–2235 | What is B stands for? I would expect to see V (Visibility). |
Adding a new option is a big deal. Could you elaborate on why you want to make these symbols hidden ones?
However, it's still useful to define them as hidden in many contexts.
Can you raise one example in the description?
I don't think you need to introduce an option for this. You can give the __start_ and __stop_ symbols hidden visibility in any object file, and the symbols in the final output file will be hidden because the linker will choose the most restrictive visibility that it sees for the visibility of the symbols in the final output file.
The real question is concrete examples of when you'd ever not want them hidden? The normal use for these symbols is always local to the module, and you want to be able to have multiple modules using the same section names.
Consider a static library that is meant to be statically linked into shared objects as a private implementation detail. Say this library provides macros/templates to its users that emit metadata into a named section, and then library code that iterates over the section. Each instance of this library inside a given shared object must iterate over its own list, not the list of whichever user of the static library happens to be first in dynamic linking symbol resolution order.
It seems like the only reason these symbols are exported is because when support for generating these symbols has been first implemented in ld.bfd, it didn't even have a concept of visibility. Later, binutils tried to make these symbols hidden, but that broke clients that depend on the old behavior (according to Hyrum's law) which is documented in https://sourceware.org/bugzilla/show_bug.cgi?id=21964
Yes that works, but it has to be done explicitly for each such symbol. We cannot change these symbols to be hidden by default for existing platforms as described above, but we would like to make them hidden by default in Fuchsia since we don't have any legacy code (yet) that would depend on the existing behavior. Introducing new option allows us to set it in the driver like we already do e.g. [for -z rodynamic](https://github.com/llvm-mirror/clang/blob/master/lib/Driver/ToolChains/Fuchsia.cpp#L50) which is a similar case.
lld/ELF/Writer.cpp | ||
---|---|---|
2231–2235 | Binding (that's what addOptionalRegular's argument is called as well), would you prefer V? |
I have updated the description to better explain the motivation and provide an example.
Yes that works, but it has to be done explicitly for each such symbol. We cannot change these symbols to be hidden by default for existing platforms as described above, but we would like to make them hidden by default in Fuchsia since we don't have any legacy code (yet) that would depend on the existing behavior. Introducing new option allows us to set it in the driver like we already do e.g. [for -z rodynamic](https://github.com/llvm-mirror/clang/blob/master/lib/Driver/ToolChains/Fuchsia.cpp#L50) which is a similar case.
Does that mean there is a visibility mismatch between source code and linker-defined symbol? e.g.
//extern char __start_f __attribute__((visibility("hidden"))); extern char __start_f; // Fuchsia wants to write code like this, but its visibility is set to hidden due to -z hidden-start-stop-symbols __attribute__((section("f"))) char *foo() { return &__start_f; }
Please correct me but if my understanding is correct, I think the explicit visibility attribute in source code would be clearer.
Thank you for the explanation. Your explanation makes sense to me. Being said that, I don't think I'd add a new option to the linker for Fuchsia, as I guess that the situation in which you want to iterate over start/end symbols is not too frequent. Also if you iterate over a known list of start/end symbols, you can define the symbols as hidden ones using attribute, so there's already an easy workaround that works on many ELF linkers.
The reason why is preferred over using explicit annotations in the source is because it matches the compiler behavior. We compile all our code with -fvisibility=hidden and we use explicit visibility annotations on symbols that should be exported. This is a standard way for controlling your ABI which is not specific to Fuchsia and is used by many other projects including LLVM. In that model, any symbol that does not have an explicit annotation is hidden. However, with __start/__stop symbols generated by lld, it's the opposite: they're exported by default and you need to use explicit annotation to make them hidden. That's confusing for developers and what we're trying to address. We would actually like to set -z hidden-start-stop-symbols in the Clang driver whenever -fvisibility=hidden is set to ensure that the compiler and linker use the same rules when it comes to symbol visibility.
I am still on the fence, but my mind can be easily changed if binutils people are ok with a -z option: https://sourceware.org/pipermail/binutils/2020-June/111440.html
Both GNU linkers now implement -z start-stop-visibility=... and binutils 2.35 will include that feature.
Please add a test, startstop-visibility.s (I would like start-stop-visibility.s, but some existing tests use the startstop- prefix).
Use -triple=x86_64 and use llvm-readelf -s to check visibility. Check both __start_foo and __stop_foo. Don't add another __start_bar.
Please mention that GNU ld and gold from binutils 2.35 onwards will support the option (
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=cae64165f47b64898c4f1982d294862cfae89a47 )
SGTM thanks! I'm also fine waiting until the GNU change lands.
(I guess @grimar may want you to use different output files for different RUN lines.)
Using different output files is fine with me.
Never mind, looks like it already landed in https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=cae64165f47b64898c4f1982d294862cfae89a47
Thanks! It really makes debugging failing test cases simpler when temporarily files are created.
(It is also my personal preference: we can use # as the comment marker. It is simpler. I'll not enforce that, though. When you write comments which are not RUN or CHECK lines, you can write ## . It makes comments stand out and avoids caveats for while some FileCheck developers want to prevent)
if (kv.second == "default")
The braces can be omitted.