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

[SR-521] Public symbols are never dead stripped #5326

Closed
allevato opened this issue Jan 12, 2016 · 12 comments
Closed

[SR-521] Public symbols are never dead stripped #5326

allevato opened this issue Jan 12, 2016 · 12 comments
Labels

Comments

@allevato
Copy link

Previous ID SR-521
Radar None
Original Reporter @allevato
Type Bug
Status Resolved
Resolution Done
Environment

Tested on OS X:
Swift version 2.2-dev (LLVM 46be9ff861, Clang 4deb154edc, Swift 51a9cea5cd)
Target: x86_64-apple-macosx10.9

Tested on Linux:
Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 1f2908b4f7)
Target: x86_64-unknown-linux-gnu

Additional Detail from JIRA
Votes 0
Component/s Compiler, Package Manager
Labels Bug
Assignee None
Priority Medium

md5: 58e0a16182b3604b18df177057c9bc29

relates to:

  • SR-1021 Don't export public symbols from static libraries by default

Issue Description:

Symbols declared with public visibility are never dead stripped by the linker, even when linking an executable where there is no expectation that the result would be linked into anything else (and thus unused symbols could be safely discarded).

Stripping these symbols is important when building an executable that links to a large library that it only uses a portion of, to prevent code bloat.

STEPS TO REPRODUCE

1. Create functions.swift, first using internal visibility:

func foo() { print("foo") }
func bar() { print("bar") }

2. Create main.swift:

bar()

3. Build an executable (example provided is for OS X):
swiftc functions.swift main.swift -Xlinker -dead_strip

4. Run nm main and observe that foo has been stripped from the executable.

5. Modify functions.swift to declare the functions with public visibility:

public func foo() { print("foo") }
public func bar() { print("bar") }

6. Build the executable again:
swiftc functions.swift main.swift -Xlinker -dead_strip

7. Run nm main and observe that foo is still present.

EXPECTED BEHAVIOR

foo should be removed because we are building an executable and it is never referenced within that binary.

OTHER NOTES

On OS X, adding the -whole-module-optimization option to swiftc has no effect.

On Linux, the behavior differs. -Xlinker -dead_strip doesn't apply here; instead, we see the following based on -whole-module-optimization:

1. Internal visibility compiled without -whole-module-optimization: foo is not stripped
2. Internal visibility compiled with -whole-module-optimization: foo is stripped
3. Public visibility regardless of the presence of -whole-module-optimization: foo is not stripped

@belkadan
Copy link

Some programs do load plugins that rely on public symbols in the executable. Why do you have public declarations in your executable?

@allevato
Copy link
Author

The example is a bit contrived to keep it small, but the same problem occurs if I use the Swift package manager with two targets—a library with public symbols, and an executable that imports the library. If the library is large and the executable only uses a small number of symbols from it, it would be nice to have the option to strip the unused code out of the final binary.

@mxcl
Copy link
Contributor

mxcl commented Jan 14, 2016

I agree it should be possible to strip unused public functions from executables. Seems like the Swift team have more pressing problems. Probably though you could write the patch.

@mxcl
Copy link
Contributor

mxcl commented Feb 19, 2016

I have added -dead-strip to release mode builds for executable targets: e08f2d9

@mxcl
Copy link
Contributor

mxcl commented Mar 8, 2016

Strictly, this is not done, one part is done, the issue described with the build-chain is still present.

@jckarter
Copy link
Member

For GNU ld, it looks like we could use --exclude-libs ALL to suppress exporting symbols from static libraries as symbols in the executable. That's probably good enough for most cases where you statically link in libraries but don't reexport them. In the fullness of time, I think we'd want to build static libraries such that their symbols have hidden visibility by default, unless explicitly reexported as public through an executable or library module built as a dylib.

@jckarter
Copy link
Member

-dead-strip is probably a bad idea because, as @drewcrawford recently discovered, we need to dynamically export the swift2_protocol_conformances and other reflection symbols from executable to be findable by dlsym in the runtime. Those symbols likely appear dead from outside in a statically linked executable.

@mxcl
Copy link
Contributor

mxcl commented Mar 21, 2016

I'll remove `--dead-strip`.

@mxcl
Copy link
Contributor

mxcl commented Mar 21, 2016

#215

@jckarter
Copy link
Member

Thanks @mxcl. I filed https://bugs.swift.org/browse/SR-1021 for a better compiler-side solution.

@swift-ci
Copy link
Contributor

Comment by Walter (JIRA)

Is there any further progress on this issue? @mxcl

@belkadan
Copy link

As noted, SR-1021 is tracking further work.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 4, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants