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

[Linux] Force the inclusion of the backtracing code when static linking. #68671

Merged
merged 3 commits into from
Sep 26, 2023

Conversation

al45tair
Copy link
Contributor

When we're statically linking the standard library, we need to force the inclusion of the backtracing code in the runtime, otherwise we don't get on-crash backtraces.

Also, add a test to make sure that this works.

rdar://115774613

When we're statically linking the standard library, we need to force
the inclusion of the backtracing code in the runtime, otherwise we don't
get on-crash backtraces.

Also, add a test to make sure that this works.

rdar://115774613
@al45tair al45tair requested a review from a team as a code owner September 21, 2023 14:48
@al45tair
Copy link
Contributor Author

@swift-ci Please test

@al45tair al45tair added Linux Platform: Linux 🍒 release cherry pick Flag: Release branch cherry picks swift 5.10 labels Sep 21, 2023
@al45tair
Copy link
Contributor Author

Explanation: When using --static-stdlib, the crash handler for the backtracing code doesn't get linked into the final binary because the backtracing code is entirely self-contained and it gets discarded by the linker. This fixes that issue by adding a reference to it to swiftrt.o, which causes the static linker to drag it in from the archive.
Risk: Low. Only affects Linux.
Original PR: #68669
Reviewed by: @mikeash
Resolves: rdar://115774613
Tests: This PR adds an explicit test to make sure that we get backtraces when a statically linked program crashes. It fails prior to the other changes in the PR, and succeeds after them.

When we're building with host tools, we should use the host's swiftrt.o
and not the one we've just built when we're trying to build tools that we
will run on the host system.

rdar://115774613
@al45tair
Copy link
Contributor Author

@swift-ci Please test

@0xTim
Copy link

0xTim commented Sep 22, 2023

Can we get this cherrypicked onto the next 5.9 monthly release?

Additionally is there a workaround for current applications?

@gwynne
Copy link
Contributor

gwynne commented Sep 23, 2023

@al45tair This is not sufficient for backtracing to work in statically linked executables. There are two other major issues:

  1. Either SWIFT_ROOT=/usr or SWIFT_BACKTRACE=swift_backtrace=/usr/libexec/swift/linux/swift-backtrace must be specified in the environment (in statically linked binaries, the dladdr() trick used to get a default root path won't find anything).
  2. Typically, (part of) the point of a statically linked executable is to use it without needing the Swift runtime libs in the final host filesystem (such as a runner Docker image). Unfortunately, the required swift-backtrace binary is not itself statically linked, which means either having a Swift toolchain installed or copying the runtime libraries to the runner environment.

In short, it doesn't work (very well) with statically linked binaries anyway 😕.

As an aside, as a workaround for the linkage problem in 5.9.0 that this PR addresses, it is sufficient to add -Xlinker -u -Xlinker _swift_backtrace_isThunkFunction to the build command (or otherwise specify the linker flag).

@al45tair
Copy link
Contributor Author

@al45tair This is not sufficient for backtracing to work in statically linked executables. There are two other major issues:

  1. Either SWIFT_ROOT=/usr or SWIFT_BACKTRACE=swift_backtrace=/usr/libexec/swift/linux/swift-backtrace must be specified in the environment (in statically linked binaries, the dladdr() trick used to get a default root path won't find anything).

I'm aware of that (and, actually, on Glibc at least, I think you can also put a copy of swift-backtrace into the same path as your executable, since the search logic in Paths.cpp should find it relative to the executable path in that case; I haven't checked that yet, but the environment variables do work). I'm hoping to document all of this at some point in a public blog post.

I have a better solution in mind in the longer term.

  1. Typically, (part of) the point of a statically linked executable is to use it without needing the Swift runtime libs in the final host filesystem (such as a runner Docker image). Unfortunately, the required swift-backtrace binary is not itself statically linked, which means either having a Swift toolchain installed or copying the runtime libraries to the runner environment.

I'm aware of the various reasons people might want a statically linked executable. I'm also working on a statically linked swift-backtrace (which will be in a separate PR) that users who want to do this could distribute.

Can we get this cherrypicked onto the next 5.9 monthly release?

There is already a 5.9 cherrypick.

Additionally is there a workaround for current applications?

As Gwynne says, you could do this:

As an aside, as a workaround for the linkage problem in 5.9.0 that this PR addresses, it is sufficient to add -Xlinker -u -Xlinker _swift_backtrace_isThunkFunction to the build command (or otherwise specify the linker flag).

We want the static version of Dispatch here.  If we don't use that version,
we'll fail the tests on the release branches (but strangely not on main
for some reason).

rdar://115774613
@al45tair
Copy link
Contributor Author

@swift-ci Please test

@al45tair al45tair merged commit 4002cc8 into apple:release/5.10 Sep 26, 2023
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Linux Platform: Linux 🍒 release cherry pick Flag: Release branch cherry picks swift 5.10
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants