What does LLDB need in order to show source code?
When the compiler compiles a function in a .swift file, it generates machine code (store in .o object files)
on debug builds, .o files come with a
__debug_infosegment, which contains addresses in the executable that can be mapped to a source file and line number, and vice versafor archiving and distribution, debug info can be linked into .dSYM bundles
the debug info linker is called
dsymutil
image and path remap
use
image list nameOfFrameworkto check whether LLDB has found the debug dSYM of a third party framework embedded in our appuse
image lookup 0xMemoryAddressHereto get more info about the current addressto remap source .dSYM paths, use
settings set target.source-map old/path new/pathtip: instead of doing this at each session, create a lldb init file that is run at the beginning of each session (point to this file in your scheme)
alternatively, each .dSYM bundle comes with a UUID.plist where we can set a
DBGSourcePathRemappingdictionary
Source path canonicalization
We can instruct the compiler to canonicalize source paths before putting them into the debug info
This is done using the
-debug-prefix-mapoptionThis way the machine-specific path prefix can be replaced by a unique, canonical placeholder name that can then be remapped to the local path in LLDB
// Clang:
-fdebug-prefix-map $PWD=/BUILDROOT
// Swift:
-debug-prefix-map $PWD=/BUILDROOTpo,p,expr vs v, frame
LLDB is both a debugger and a compiler
based on whether our LLDB command sides in the debugger or compiler side of LLDB, they might or or not fail
(debugger side)
vandframeget their type information from LLDB Debug Info (which in turn gets types from Swift reflection metadata_(compiler side)
p,po,exprget type information from ModulesModules are how the compiler organizes type declarations
How do we start diagnosing an issue that is happening on the compiler side?
new in Xcode 14, we have
swift-healthcheckLLDB commandit helps understanding if and why a module import failed
it saves a .log of the Swift expression evaluator configuration
How LLDB’s compiler finds Swift modules?
It’s the build system’s job to package up the modules so LLDB can find them
Modules from system frameworks stay in the SDK (anyone can find them via
$ xcrun --show-sdk-path), LLDB will find a matching SDK to read them from as it’s attaching to your programwhen debugging straight from the .o object files, LLDB will find all non-SDK modules where they were at build time
dsymutilcan package a debug info archive (.dSYM bundle) for every dynamic library, framework or dylib, and executableeach .dSYM bundle can contain binary Swift modules, which may contain bridging headers .h, textual Swift interface files .swiftinterface, and most importantly, debug info.
for static archives, a Swift module needs to be registered with the linker (
ld ... -add-ast-path /path/to/My.swiftmodule)for dynamic libraries and executables, the build system will do this automatically for you. But for static archives, this is needed because static archives are not produced by the linker
Xcode’s build system should do this for you, but you need to be aware if you have your own build system
You can check your build log to verify that that everything is linked, or use dsymutil to dump the symbol table of your executable and grep for “swiftmodule”:
dsymutil -s MyApp | grep .swiftmoduleIn Linux the swift driver supports a -modulewrap flag that converts binary Swift module files into objects that you can link into your binary together with the rest of the debug info. LLDB will find it there
swiftc -modulewrap My.swiftmodule -o My.swiftmodule.oAvoiding serialized search paths in Swift modules
The Swift compiler will serialize Clang header search paths and other related options into the binary .swiftmodule files
This is great, because it makes importing their Clang module dependencies just work during the build
But when building on a different machine, these local paths can be detrimental
Before shipping a binary .swiftmodule to another machine, set the
-no-serialize-debugging-optionscompiler flagIn Xcode this is controlled via the
SWIFT_SERIALIZE_DEBUGGING_OPTIONSsettingyou can then reintroduce these search paths in LLDB with one of the following settings:
settings set target.swift-extra-clang-flags …
settings set target.swift-framework-search-paths …
settings set target.swift-module-search-paths …