Sitemap

Remote debug of macOS application using Xcode

--

Note: my goal is create short and accurate guide about macOS remote debugging, to be used as fast reference

Part 1: (This Article) Remote debug of macOS application using Xcode
Part 2: Automated Remote debug of macOS application using Xcode

When you are iOS developer, testing and debugging your application on different environments is easy.
iOS simulators provide ability to use any iOS device with any iOS version on it.
Want to test on real device — just connect it via USB/WiFi and do your best!

But we are macOS developers. And the best macOS simulator is virtual machine.
Want to debug your application on another device or macOS version?
Install Xcode there, put all your sources there…nah. Too complicated and hard.
Looks like the only fast way is to using logs. Officially — yes, practically — NO!

Remote debug of macOS application is simple!

This article describes a technique of debugging macOS applications REMOTELY on another macOS.
It is important because we want to debug…

  • … on another (usually older) version of macOS
  • … on QA’s machine with specific environment
  • … EndpointSecurity client with AUTH_OPEN (and like) subscription (more details in article)
  • … on dedicated test Virtual Machine, remaining work Mac to be clean

How remote debug works

In remote scenario, one machine (Host) acts like a debugger machine (where the debugger runs) and another one (Target) acts like a debuggee (where the application runs).
These machines must be visible to each other over the network.
In few words, here is the scenario

  • application in launched on Target machine
  • debugserver is launched on Target machine too. It attaches to the application and listens on specific port for debugger commands
  • on Host machine, the debugger (lldb / Xcode) is launched. It connects to the debugserver over the network
  • debugger on Host machine interacts with debugserver on Target, sending debug commands

lldb process connect

Approach shown in this article uses public lldb debugger capabilities.
You could remotely debug your iOS / macOS / *OS application from command-line using lldb debugger.

Less words — more action!

Prepare the environment

  1. On Host, Reveal hidden Xcode feature that allows remote debug.
    In Terminal.app, run: defaults write com.apple.dt.Xcode IDEDebuggerFeatureSetting 12
    Restart Xcode
  2. Copy debugserver process from Xcode /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/debugserver to the Target machine
  3. Place the executable (built on Host) you want to debug to the Target machine

Debug!

Start debugserver on Target machine by attach debugserver to the application.
Important here that IP address is address of the Host machine or 0.0.0.0 to allow all connections
- to attach to already running application, run
…../debugserver ip:port --attach=pid
…../debugserver ip:port --attach=name
- launch application and attach on startup
…../debugserver ip:port /path/to/executable

Get Volodymyr Alkenso Vashurkin’s stories in your inbox

Join Medium for free to get updates from this writer.

On Host machine, perform attach-over-network.
In Xcode, adjust the Scheme you are going to debug

  1. Switch Launch to ‘Custom LLDB commands’
  2. Input the command process connect connect://ip:port
    Note that ip is the IP address of the Target machine

3. Press ‘Start’ button in Xcode to perform connect and debug

4. Enjoy remote debug on macOS using Xcode!

Speedup debugger-attach with debug symbols

The debug itself works great.
But when you Host and Target machines are of different OS versions, the attaching may take a bit long annoying time.
That happens because lldb cannot find proper debug symbols and reads them from remote process memory.

For example, the same situation is for iOS debugging when Xcode needs iOS symbols for proper on-device debug.
But for iOS the process is automated, for macOS we should do it manually

  1. Collect debug symbols from Target machine.
    I’ve used opensource tool dyld-shared-cache-extractor
    https://github.com/keith/dyld-shared-cache-extractor/
  2. Determine the OS version and build number of Target machine
    You can use Terminal commands for that
    - sw_vers -productVersion → 12.6.1
    - sw_vers -buildVersion → 21G217
  3. Copy all symbols to Host to the folder named as “12.6.1 (21G217)” located at ~/Library/Developer/Xcode/macOS DeviceSupport (create that folder if it does not exist)
    See image below with correct path structure example.
  4. Restart Xcode.
    Now debug symbols would be read from disk, which is much more faster than from remote process memory
Press enter or click to view image in full size

--

--