Skip to content
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

Add -dead_strip / --gc-sections for release builds #4135

Merged

Conversation

keith
Copy link
Member

@keith keith commented Feb 13, 2022

In the past it was unsafe to pass -dead_strip because there was some
required swift metadata that was stripped. It seems that at this point all
of those cases are either fixed or marked as @llvm.used, so passing
these flags should safely reduce binary size in some cases. If there are
other cases where this isn't safe we should likely annotate them as
@llvm.used.

Related: https://bugs.swift.org/browse/SR-521 #215

@tomerd
Copy link
Contributor

tomerd commented Feb 14, 2022

cc @kubamracek @jckarter @compnerd

@tomerd
Copy link
Contributor

tomerd commented Feb 14, 2022

thanks @keith this makes sense based on what @kubamracek was saying on another thread. couple of questions / ideas:

  1. should this be behind a flag so that its possible to disable/enable (ie enabled by default but possible to disable If causes issues as an escape hatch)
  2. do we need to add a small unit test? especially if do add the flag (which I lean towards thinking we should)
  3. do we know that this also works fine on Linux and Window which use different linkers afaik?

Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CC: @kubamracek (I believe Kuba was involved in the changes for the metadata preservation).

Sources/Build/BuildPlan.swift Show resolved Hide resolved
@keith keith force-pushed the ks/add-dead_strip-gc-sections-for-release-builds branch from b0b2d01 to b175e94 Compare February 14, 2022 17:39
@keith
Copy link
Member Author

keith commented Feb 14, 2022

A flag sounds fine to me, would folks prefer opt-in or opt-out? I'm not sure how much testing an opt-in flag would get at this point, but I'll defer to you all for your risk preference.

I did test this on Linux and I think --gc-sections is safe for all ELF linkers

@tomerd
Copy link
Contributor

tomerd commented Feb 14, 2022

@keith I would go with opt out given that @kubamracek believes this is safe enough. we need @compnerd init on Windows too. lmk if you need guidance on how to expose a flag and pipe it through the different layers

@kubamracek
Copy link

kubamracek commented Feb 14, 2022

I'm definitely supportive of this, I'm not aware of any problems/bugs in this area (but TBH I have mostly only worked with Darwin / Mach-O / ld64, and almost not at all with other platforms / file formats / linkers). I am even supportive in making dead stripping be the default behavior, but I want to point out that there are cases where dead-stripping will affect a program -- and mostly it's "shady" things like dlsym'ing for an otherwise unused symbol, and probably only really affects C code and not Swift code. Before we make dead-stripping the default, we should acknowledge that stuff like this might be affected. I personally think it's the right choice (and programs relying on not-dead-stripping would either need to opt out, or fix their code, there's some simple options like __attribute__((used))), but I wonder what the thinking of others is :)

@tomerd
Copy link
Contributor

tomerd commented Feb 14, 2022

its also worth mentioning that at the current state of things, -dead_strip would have little effect on Swift code, and would mostly effect C code built with SwiftPM

@keith
Copy link
Member Author

keith commented Feb 14, 2022

Updated with a flag!

@compnerd
Copy link
Member

Please do a test build on Windows just to make sure that things don't break.

@tomerd
Copy link
Contributor

tomerd commented Feb 14, 2022

Please do a test build on Windows just to make sure that things don't break.

@compnerd @shahmishal is there a way to trigger CI for Windows for this change? maybe a dummy PR with cross-repo test?

@tomerd
Copy link
Contributor

tomerd commented Feb 14, 2022

@swift-ci please smoke test

@shahmishal
Copy link
Member

Please do a test build on Windows just to make sure that things don't break.

@compnerd @shahmishal is there a way to trigger CI for Windows?

Hopefully soon we will be able to from SwiftPM, however for now you will have to do cross PR to trigger Windows testing.

@tomerd
Copy link
Contributor

tomerd commented Feb 14, 2022

Hopefully soon we will be able to from SwiftPM, however for now you will have to do cross PR to trigger Windows testing.

thanks @shahmishal created swiftlang/swift#41374

what is the trigger phrase for Windows verification?

@shahmishal
Copy link
Member

@swift-ci test Windows

@compnerd
Copy link
Member

@shahmishal does that now trigger a different job? There are two separate builds - the @swift-ci please test Windows builds and tests the toolchain (which is why it is quick); the full toolchain build is almost twice as long but builds a full toolchain image (and tests a bit more, though still in sufficient for this as of yet :-()

@tomerd
Copy link
Contributor

tomerd commented Feb 15, 2022

this is pending verification on Windows, see discussion on swiftlang/swift#41374

@tomerd
Copy link
Contributor

tomerd commented Feb 15, 2022

@keith in the meantime maybe add an entry in the change log to document the change?

In the past it was unsafe to pass -dead_strip because there was some
swift metadata that could be stripped. It seems that at this point all
of those cases are either fixed or marked as @llvm.used, so passing
these flags should safely reduce binary size in some cases. If there are
other cases where this isn't safe we should likely annotate them as
@llvm.used anyways.

Related: https://bugs.swift.org/browse/SR-521

swiftlang#215
@keith keith force-pushed the ks/add-dead_strip-gc-sections-for-release-builds branch from cc153ab to 2afc913 Compare February 15, 2022 18:33
CHANGELOG.md Show resolved Hide resolved
@keith keith force-pushed the ks/add-dead_strip-gc-sections-for-release-builds branch from 6e3ed66 to 9cc0b75 Compare February 15, 2022 18:37
@tomerd
Copy link
Contributor

tomerd commented Feb 15, 2022

@swift-ci please smoke test

Copy link
Contributor

@tomerd tomerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pending verification on Windows, see discussion on swiftlang/swift#41374

@tomerd
Copy link
Contributor

tomerd commented Feb 15, 2022

@swift-ci please smoke test

@compnerd
Copy link
Member

:-( it seems that something isn't really correct:

S:\Library\Developer\Toolchains\unknown-Asserts-development.xctoolchain\usr\bin\swiftc.exe -Xlinker -debug -L S:\SourceCache\swift-win32\.build\x86_64-unknown-windows-msvc\release -o S:\SourceCache\swift-win32\.build\x86_64-unknown-windows-msvc\release\Calculator.exe -module-name Calculator -lSwiftCOM -lcassowary -emit-executable @S:\SourceCache\swift-win32\.build\x86_64-unknown-windows-msvc\release\Calculator.product\Objects.LinkFileList -target x86_64-unknown-windows-msvc -lUser32 -lComCtl32 -sdk S:\Library\Developer\Platforms\Windows.platform\Developer\SDKs\Windows.sdk -libc MD -I S:\Library\Developer\Platforms\Windows.platform\Developer\Library\XCTest-development\usr\lib\swift\windows\x86_64 -L S:\Library\Developer\Platforms\Windows.platform\Developer\Library\XCTest-development\usr\lib\swift\windows

Note that the -Xlinker /OPT:REF is missing. That was built with -c release.

@keith
Copy link
Member Author

keith commented Feb 15, 2022

I inverted the boolean when we renamed from disable -> enable, fixed, sorry about that! It didn't break the tests because it was inverted there too after that change. Is there a way to test the actual flag behavior (like lit in LLVM)?

@tomerd
Copy link
Contributor

tomerd commented Feb 15, 2022

@swift-ci please smoke test

@compnerd
Copy link
Member

compnerd commented Feb 16, 2022

S:\Library\Developer\Toolchains\unknown-Asserts-development.xctoolchain\usr\bin\swiftc.exe -Xlinker -debug -L S:\SourceCache\swift-win32\.build\x86_64-unknown-windows-msvc\release -o S:\SourceCache\swift-win32\.build\x86_64-unknown-windows-msvc\release\Calculator.exe -module-name Calculator -emit-executable -Xlinker /OPT:REF @S:\SourceCache\swift-win32\.build\x86_64-unknown-windows-msvc\release\Calculator.product\Objects.LinkFileList -target x86_64-unknown-windows-msvc -lUser32 -lComCtl32 -lOle32 -lPortableDeviceGuids -sdk S:\Library\Developer\Platforms\Windows.platform\Developer\SDKs\Windows.sdk -libc MD -I S:\Library\Developer\Platforms\Windows.platform\Developer\Library\XCTest-development\usr\lib\swift\windows\x86_64 -L S:\Library\Developer\Platforms\Windows.platform\Developer\Library\XCTest-development\usr\lib\swift\windows

Built and ran the calculator demo, seems to be fine, and the linker was also fine with the flags. I think that this should be fine from the Windows side at least. And the command line indicates that the flag is now there.

@keith
Copy link
Member Author

keith commented Feb 16, 2022

thanks for testing!

@tomerd tomerd merged commit 3e14a79 into swiftlang:main Feb 16, 2022
@tomerd
Copy link
Contributor

tomerd commented Feb 16, 2022

thanks @keith

@keith
Copy link
Member Author

keith commented Feb 16, 2022

Thanks all!

@keith keith deleted the ks/add-dead_strip-gc-sections-for-release-builds branch February 16, 2022 21:22
@drodriguez
Copy link
Contributor

@keith: do you remember which linkers and versions did you use to test in Linux ELF? With a recent LLD you have swiftlang/llvm-project@6d2d3bd which enables GC of the start/stop symbols, which seems to be affecting the Swift metadata section symbols in our setup.

@keith
Copy link
Member Author

keith commented Feb 25, 2022

Interesting, I just tried the defaults, do you have a repro case I can debug with?

@drodriguez
Copy link
Contributor

Not with the upstream build system, sadly. I was just trying to compile a newer SwiftPM with a recently compiled SwiftPM that includes this (and pointing to a quite recent LLD) and started seeing these linking problems about the start and stop symbols being hidden undefined. I think it will need a fix in how the sections are declared in https://github.com/apple/swift/blob/main/stdlib/public/runtime/SwiftRT-ELF.cpp but a first idea adding "R" to the section declaration did fix many test in the check-swift test suite, but not all of them (IIRC there were 76 left, many of them crashes).

I will try to keep looking. For the time being I can work around it with --disable-dead-strip so it is not the end of the world.

@keith
Copy link
Member Author

keith commented Mar 1, 2022

I think the assumption from folks here was generally that things should be correctly referenced / non-strippable today, so if that's not the case we may have to temporarily reconsider this default unless we can come up with a fix for those

@finagolfin
Copy link
Contributor

I just hit this when building the latest Mar. 9 trunk source snapshot of the toolchain natively on my Android AArch64 phone that uses lld, which is fixed by disabling this flag by default in the SPM source. This may be a recent lld regression, which this new flag triggers for us on Android, as this guy reported the issue on linux with lld 13, unrelated to this SPM flag, on the forum last month, or maybe lld or clang 13 enabled this flag by default all of a sudden on linux too.

Strangely, my Android CI, which cross-compiles an Android SDK and several packages against it, worked fine on the first run with this new Mar. 9 SPM, I'll look into that further.

There may be issues with this flag and lld on ELF platforms interacting badly with swiftrt.o, we'll need to investigate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants