Search code examples
cocoaswiftread-eval-print-looplldbf-script

Access a Swift REPL in Cocoa programs


I can attach LLDB to a program written in Swift and access the REPL, either from within Xcode or by running:

lldb -n ProcessName
(lldb) repl
  1>

However, if I attach LLDB to a process which doesn't have the Swift runtime, the REPL isn't very useful. For example:

lldb -n Finder
Process 218 stopped
Executable module set to "/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder".
Architecture set to: x86_64-apple-macosx.
(lldb) repl
  1> import Cocoa
error: Couldn't lookup symbols:
  __swift_FORCE_LOAD_$_swiftAppKit
  __swift_FORCE_LOAD_$_swiftCoreGraphics
  __swift_FORCE_LOAD_$_swiftObjectiveC
  __swift_FORCE_LOAD_$_swiftDispatch
  __swift_FORCE_LOAD_$_swiftDarwin
  __swift_FORCE_LOAD_$_swiftFoundation

Any idea on how to load the Swift runtime into a process which isn't linked against it already? This could be a very useful alternative to e.g. injecting F-Script.


Solution

  • dlopen() to the rescue!

    Download this script and save it e.g. to ~/.lldb/inject-swift-repl

    Then run lldb -n Finder --source .lldb/inject-swift-repl to inject all necessary libraries. Note that you need to disable SIP to mess with the Finder. Also note that sometimes I had to exit LLDB and re-run the script, because some dlopen calls failed and returned 0.