Skip to content

Conversation

@Jnosh
Copy link
Contributor

@Jnosh Jnosh commented Nov 29, 2016

Previously the default was used, implying LLDB specific tuning only for Darwin targets.

For example, the compilation flags (DW_AT_APPLE_flags attribute) are only emitted when tuning for LLDB. With Swift, LLDB uses this attribute mostly as a fallback source for the compilation options specified in the embedded serialized AST.
However, it is the only source for LLDB on whether a custom '-resource-dir' was used.

cf. lldb's SwiftASTContext::CreateInstance

Motivation
In my testing this enabled LLDB to find the stdlib that was used at compile time via '-resource-dir' when remote-debugging linux targets.

Another approach might be to add a compiler flag (similar to clang's -ggdb/-glldb) but that doesn't seem to be particularly useful to me, given that LLDB is (AFAIK) the only debugger capable of debugging Swift in any meaningful way at the moment.
Ditto for potential adverse effects on GDB debugging by tuning for LLDB.

That said I would very much appreciate feedback in this regard; this is basically just guesswork on my part...

Test
I added a simple test to check whether the LLDB-tuning specific DW_AT_APPLE_flags attribute is emitted into the assembled object files.
There is no test for whether the exact compiler options end up being emitted but there are already existing tests that check that certain compiler options are emitted to IR and the IR -> object file transformation should be covered by LLVM.

@jrose-apple
Copy link
Contributor

We are very much trying to kill this set of flags, and LLDB already needs to use its own resource dir rather than the one a project was built with (if different). cc @scallanan, @jimingham, @adrian-prantl.

@adrian-prantl
Copy link
Contributor

There are two components to this:

  1. @jrose-apple is right that DW_AT_APPLE_flags attribute is being phased out.
  2. The debugger tuning option (clang's -glldb) is a relatively new addition and here to stay. It is used by the LLVM backend to, for example, avoid certain DWARF constructs that are valid but not handled correctly by specific debuggers. Since swift is only debuggable by LLDB we should be setting this unconditionally.

@adrian-prantl
Copy link
Contributor

LGTM

@adrian-prantl
Copy link
Contributor

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 4980cd214c67257aba277213a1cebce228775d14
Test requested by - @adrian-prantl

@adrian-prantl
Copy link
Contributor

let's try that again:
@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 4980cd214c67257aba277213a1cebce228775d14
Test requested by - @adrian-prantl

@tfiala
Copy link
Contributor

tfiala commented Nov 29, 2016

@swift-ci Please clean smoke test Linux platform

1 similar comment
@tfiala
Copy link
Contributor

tfiala commented Nov 29, 2016

@swift-ci Please clean smoke test Linux platform

@tfiala
Copy link
Contributor

tfiala commented Nov 29, 2016

(Trying a clean Linux smoke test since I don't trust our incremental builds used by multiple PR build runs...)

@Jnosh Jnosh force-pushed the debugger-tune-lldb branch from 4980cd2 to bbcb968 Compare November 29, 2016 19:50
@Jnosh
Copy link
Contributor Author

Jnosh commented Nov 29, 2016

Thanks for the feedback!

I updated the commit message and changed the test not to use DW_AT_APPLE_flags. Instead I switched to the same approach used by the corresponding LLVM test.

(Sorry for killing the running tests)

@tfiala
Copy link
Contributor

tfiala commented Nov 29, 2016

Hey all, I'm going to try to repro the test failures on Ubuntu. Please hold off on merging until we can track down why the REPL tests are failing. I'm starting to look at this now.

Previously the default was used, implying LLDB specific tuning only for Darwin targets.
@Jnosh Jnosh force-pushed the debugger-tune-lldb branch from bbcb968 to cab3137 Compare November 29, 2016 20:15
@Jnosh
Copy link
Contributor Author

Jnosh commented Nov 29, 2016

Fixed my botched copy&paste job. Sorry about that.

%llvm-readobj is not available as a lit substitution. Is it OK to use plain llvm-readobj or should I add the substitution to lit.cfg?

And with regard to LLDB, do I understand correctly that the recommended approach would be to use an entire ('custom') toolchain and to use that toolchain's LLDB to debug targets built against it?
Thanks again for the help!

@tfiala
Copy link
Contributor

tfiala commented Nov 29, 2016

Hi @Jnosh,

And with regard to LLDB, do I understand correctly that the recommended approach would be to use an entire ('custom') toolchain and to use that toolchain's LLDB to debug targets built against it?
Thanks again for the help!

I think you're asking if you need to use an LLDB that matches the Swift compiler that you're using to build programs that you want to build. i.e. if you modify Swift, build a Swift compiler, and build programs with that modified Swift compiler, you do need to use the corresponding LLDB that goes with that Swift. Swift and LLDB currently are joined at the hip, as deep internals of Swift are accessed by the debugger to handle running Swift expressions and printing variables from Swift code.

Did I answer the right question here?

@tfiala
Copy link
Contributor

tfiala commented Nov 29, 2016

(Also, please note we're still trying to reproduce the Linux issue, so please do not merge this change in until we give an all clear. Thanks!)

@tfiala
Copy link
Contributor

tfiala commented Nov 30, 2016

@swift-ci Please test Linux platform

1 similar comment
@tfiala
Copy link
Contributor

tfiala commented Nov 30, 2016

@swift-ci Please test Linux platform

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - cab3137
Test requested by - @tfiala

@tfiala
Copy link
Contributor

tfiala commented Nov 30, 2016

@swift-ci Please clean test Linux platform

(clean again...)

@tfiala
Copy link
Contributor

tfiala commented Nov 30, 2016

@swift-ci Please clean test Linux platform

@Jnosh
Copy link
Contributor Author

Jnosh commented Nov 30, 2016

Hi Todd,

I think you're asking if you need to use an LLDB that matches the Swift compiler that you're using to build programs that you want to build. i.e. if you modify Swift, build a Swift compiler, and build programs with that modified Swift compiler, you do need to use the corresponding LLDB that goes with that Swift. Swift and LLDB currently are joined at the hip, as deep internals of Swift are accessed by the debugger to handle running Swift expressions and printing variables from Swift code.

It's more that I'm trying to use a standard library not located in the toolchain that LLDB is in. Let me give you some context:

I'm cross-compiling an executable for a Linux target from a macOS host. To do so I use the -resource-dir flag to point swiftcat a Linux toolchain so it can find the Linux stdlib. This part is working fine.

Now I'm trying to remote debug the executable using LLDB which also works except for LLDB of course not finding a matching stdlib for the Linux target. I can just copy the Linux stdlib into the OS X toolchain that I'm using but I was trying to avoid that since I'm mostly using the Xcode toolchain or development snapshots and I'd prefer not to modify those installations.

I was looking at LLDB for unrelated reasons and noticed that it will use the -resource-dir set at compile time if the compile flags are available which is what ultimately lead me here.

My current thinking is that it's probably cleanest to just create a separate toolchain for this purpose and not use the Xcode or Library/Developer toolchains in combination with -resource-dir at all.
i.e. build a separate macOS toolchain that also contains a Linux stdlib and use lldb (and swiftc) from that toolchain so it can simply find the target stdlib in its own toolchain.

Would that be a sensible approach?

@tfiala
Copy link
Contributor

tfiala commented Nov 30, 2016

[For posterity's sake: note after I forced a clean build on the PR Linux (full build) tester, we got a good build. To me, this -- combined with the other non-PR CI not seeing this issue -- leads me to believe something in the incremental PR building across PRs is likely not rebuilding properly.]

@Jnosh, thanks for clarifying what you're trying to accomplish!

I'm cross-compiling an executable for a Linux target from a macOS host. To do so I use the -resource-dir flag to point swiftcat a Linux toolchain so it can find the Linux stdlib. This part is working fine.

You mentioned it later on, but I would expect the way to handle this would be to create an SDK for Linux that lives on the macOS side. This would allow a macOS-side lldb to connect to the Linux binaries pushed over to the Linux target, and (if the SDK lookup code is working correctly) find the Linux binaries on the macOS host.

I haven't done this yet, and I would not at all be surprised if there is work to be done to resolve Linux SDK-related content properly on the local macOS end. You may be the first forging into those waters, although I'd expect this to eventually be an extremely useful workflow for Swift-based server development for those already on macOS.

I'm also unclear on whether using a macOS-side Linux SDK requires a separate toolchain, or whether it suffices to just specify the SDK to the swiftc from your locally built swiftc (or the one from Xcode 8.x).

Including @jrose-apple, who might have a better answer here.

@tfiala
Copy link
Contributor

tfiala commented Nov 30, 2016

@swift-ci Please smoke test Linux platform

@tfiala
Copy link
Contributor

tfiala commented Nov 30, 2016

(Trying to unclog the macOS smoke test)

@swift-ci Please smoke test OS platform

@Jnosh
Copy link
Contributor Author

Jnosh commented Dec 1, 2016

@tfiala, thanks for taking the time!

I'm cross-compiling an executable for a Linux target from a macOS host. To do so I use the -resource-dir flag to point swiftcat a Linux toolchain so it can find the Linux stdlib. This part is working fine.

You mentioned it later on, but I would expect the way to handle this would be to create an SDK for Linux that lives on the macOS side. This would allow a macOS-side lldb to connect to the Linux binaries pushed over to the Linux target, and (if the SDK lookup code is working correctly) find the Linux binaries on the macOS host.

A Linux SDK in this context would be like the macOS, iOS, ... SDKs? i.e. collection of headers/modules, objects to link against, ...?

I haven't done this yet, and I would not at all be surprised if there is work to be done to resolve Linux SDK-related content properly on the local macOS end.

Yeah, the locations I came across while looking into this and a few other issues generally dealt with SDKs only for Darwin targets.

You may be the first forging into those waters, although I'd expect this to eventually be an extremely useful workflow for Swift-based server development for those already on macOS.

Agreed. Although I'm currently compiling a standalone target (hobby Kernel) so I'm mostly avoiding the SDK issues.

I'm also unclear on whether using a macOS-side Linux SDK requires a separate toolchain, or whether it suffices to just specify the SDK to the swiftc from your locally built swiftc (or the one from Xcode 8.x).

From what (little) I can tell, using the normal macOS toolchain should mostly work just fine once the compiler/lldb/... know how to find other SDKs. I'm actually pretty impressed at how flexible the compiler is in this regard already. 👍
From what I can tell all that's needed toolchain-wise is the Swift stdlib (and module overlays) for the target platform. (Which might conceivable also migrate to the SDK once binary compatibility is ironed out?)

Basically I just drop the usr/lib/swift/linux/x86_64/* and usr/lib/swift_static/linux/* parts of a Linux toolchain into a macOS toolchain and swiftc can compile objects for x86_64 Linux.
Linking is the only part that swiftc can't manage on its own yet. As you mentioned, an SDK to link against would be needed (+ compiler_rt) and the linker invocation would have to go through clang (with e.g. -use-ld=lld) instead of ld but ideally not much more than that...

LLDB also seems to work fairly well. Symlink usr/lib/swift into the toolchains LLDB.framework/Resources and the toolchain LLDB finds the Linux stdlib module.
Remote debugging Linux Swift binaries should probably work for the most part at that point.

@jrose-apple
Copy link
Contributor

I'm not quite sure what to say here. Clearly it's important for LLDB to find the Linux stdlib and such, as well as any headers (and other Swift modules) you're using in the target you're remote-debugging. At the same time, reading that automatically from the built library's debug info may eventually be incorrect, since LLDB has intimate knowledge of certain standard library types. We probably need a real story here in general—eventually there'll be a tension between "emulate the build environment as close as possible" and "LLDB and swiftc are tied to a particular version of the Swift standard library".

@jrose-apple
Copy link
Contributor

I don't think what you're doing now is likely to cause problems, though, as long as you're using an lldb you built alongside your swiftc.

@slavapestov
Copy link
Contributor

@jrose-apple Can we merge this?

@jrose-apple
Copy link
Contributor

Ah, yes, this whole extra discussion isn't really about the debugger tuning directly.

@swift-ci Please smoke test

@jrose-apple jrose-apple merged commit b889e7e into swiftlang:master Jan 11, 2017
@Jnosh Jnosh deleted the debugger-tune-lldb branch May 19, 2017 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants