-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
[ld.lld] do not add --gc-sections by default #11577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
CI failure:
So treat this as a conversation starter w.r.t. |
To remove confusion: the first diff removed |
For the record, https://builds.hut.lavatech.top/~andrewrk/job/23490 seems to be failing on master too. |
When building object files, `zig cc` will instruct lld to remove unused sections via `--gc-sections`. This is problematic cgo builds that don't explicitly use C code. Briefly, go builds cgo executables as follows*: 1. build `_cgo_.o`, which links (on linux_amd64 systems) to `/usr/local/go/src/runtime/race/race_linux_amd64.syso`. 2. That `.syso` contains references to symbols from libc. If the user program uses at least one libc symbol, it will link correctly. However, if Go is building a cgo executable, but without C code, the sections from `.syso` file will be garbage-collected, leaving a `_cgo_.o` without any references to libc, causing the final linking step to not link libc. Until now, this could be worked around by `-linkmode external` flag to `go build`. This causes Go to link the final executable using the external linker (which implicitly links libc). However, that flag brings in a whole different world of worms. I assume the `gc_sections` is an optimization; I tried to re-add `--gc-sections` to the final executable, but that didn't go well. I know removing such an optimization may be contentious, so let's start the discussion here. Quoting @andrewrk in [1] (it was about `--as-needed`, but the point remains the same): > The C source code for the temporary executable needs to have dummy > calls to getuid, pthread_self, sleep, and every other libc function > that cgo/race code wants to call. I agree this is how it *should* work. However, while we could fix it for go, I don't know how many other systems rely on that, and we'll never know we've fixed the last one. The point is, GCC/Clang does not optimize sections by default, and downstream tools rely on that. If we want to consider `zig cc` a drop-in clang replacement (except for `-fsanitize=undefined`, which I tend to agree with), then it should not be optimizing the intermediate object files. Or at least have a very prominent fine-print that this is happening, with ways to work around it. Fixes ziglang#11398 Fixes golang/go#44695 Fixes golang/go#52690 [*]: Empirically observed with `CGO_ENABLED=1 go test -race -x -v` [1]: golang/go#52690 (comment)
For the record, I added |
The Zig project is about rebuilding systems programming from the ground up, re-examining assumptions, and making different decisions where they are warranted. Fully imitating GCC including its limitations is not a goal we have. In fact that already exists, it's Clang! Ultimately, the downstream tools need improvements in this case, not Zig. |
When building object files,
zig cc
will instruct lld to remove unusedsections via
--gc-sections
. This is problematic for cgo builds that don'texplicitly use C code. Briefly, go builds cgo executables as follows*:
_cgo_.o
, which links (on linux_amd64 systems) to/usr/local/go/src/runtime/race/race_linux_amd64.syso
..syso
contains references to symbols from libc.If the user program uses at least one libc symbol, it will link
correctly. However, if Go is building a cgo executable, but without C
code, the sections from
.syso
file will be garbage-collected, leavinga
_cgo_.o
without any references to libc, causing the final linkingstep to not link libc.
Until now, this could be worked around by
-linkmode external
flag togo build
. This causes Go to link the final executable using theexternal linker (which implicitly links libc). However, that flag brings
in a whole different world of worms.
I assume the
gc_sections
is an optimization; I tried to re-add--gc-sections
to the final executable, but that didn't go well. I knowremoving such an optimization may be contentious, so let's start the
discussion here. Quoting @andrewrk in 1 (it was about
--as-needed
,but the point remains the same):
I agree this is how it should work. However, while we could fix it for
go, I don't know how many other systems rely on that, and we'll never
know we've fixed the last one. The point is, GCC/Clang does not optimize
sections by default, and downstream tools rely on that. If we want to
consider
zig cc
a drop-in clang replacement (except for-fsanitize=undefined
, which I tend to agree with), then it should notbe optimizing the intermediate object files. Or at least have a very
prominent fine-print that this is happening, with ways to work around
it.
Fixes #11398
Fixes golang/go#44695
Fixes golang/go#52690
[*]: Empirically observed with
CGO_ENABLED=1 go test -race -x -v