Swift Debugging on Android - Current State

The ability to debug Swift code running on Android is one of the priorities of the Android project board. Related efforts are tracked under: Get this lldb working for Android debugging · Issue #10831 · swiftlang/llvm-project · GitHub

As a contributor, I worked on two topics:

1. Making LLDB work on Android

When developing an Android app (APK), the debugging context is slightly different from other platforms. First, debugging is done remotely, with lldb-server running on the device, inside the sandboxed environment of the app. Second, there is a JVM, with many libraries loaded after launch, and code segments generated on the fly. The Swift code to debug is often located in one of these shared libraries. Finally, the Swift Core Libraries use Android-specific implementations for types such as String and Array. This is due to constraints related to pointer tagging on Android.

All these aspects expose issues in LLDB that do not appear on other platforms.

Here is a list of known issues:

All these fixes are available on my work branch: GitHub - gmondada/llvm-project at gab/swift-lldb-patches

2. Swift debugging in VS Code

Swift debugging is already well supported in VS Code, thanks to the lldb-dap extension. See Configuring VS Code for Swift Development | Swift.org

To provide a good user experience on Android, the extension needs to manage these steps:

  • Launch the APK on the remote device and keep it suspended (displaying “Waiting for Debugger”) until the debugger is attached
  • Start lldb-server on the device
  • Establish the connection with lldb-server and attach to the app process
  • Set all breakpoints
  • Resume the application execution
  • Clean up everything (ADB tunnels, unix-sockets, temp files...) when the debug session ends

I implemented the logic to automate these steps on the following branch: GitHub - gmondada/llvm-project at gab/lldb-dap-android

The current implementation works only with a version of lldb-dap that includes all the fixes mentioned above. It expects an Android device (or emulator) to be connected, and the ADB server running.

To enable Android debugging, your .vscode/launch.json file must look like:

{
  "configurations": [
    {
      "type": "lldb-dap",
      "request": "launch",
      "name": "Hello Swift",
      "androidComponent": "org.example.helloswift/.MainActivity"
    }
  ]
}

The extension does not handle app compilation and installation on the device. However, this can be automated by using a preLaunchTask.

8 Likes

Thanks for writing this up, Gabriele! You've made a lot of progress and helped surface a lot of specific issues. I'm excited that we are a lot closer than we were even a few weeks ago to a usable debugging setup for Android.

1 Like

Android support in the VS Code extension (see description above) needs some additional work before a PR can be opened. However, if there are major requirements or blockers that could prevent this work from being merged upstream, I would like this to be raised and discussed before the PR.

For this reason, I am summarizing here how the solution is currently structured.

As suggested on Slack by @tracymiranda in a discussion with @Joannis_Orlandos, @ktoso and others, it would be great to start this discussion at FOSDEM.

Current implementation

  • The goal is to debug Swift on Android, but nothing in the extension is specific to Swift. The extension can be used for native debugging of any language supported by LLDB.
  • The extension does not support Java, Kotlin, or JDWP based debugging. It is an LLDB based debugger by nature.
  • Android support is implemented on the TypeScript side of the extension, not in the C++ adapter.
  • The solution implements an ADB client and a minimalist JDWP client. JDWP is only used to dismiss the “Waiting for Debugger” popup.
  • The implementation tries to be as little intrusive as possible:
    • Android specific code is grouped in a dedicated module.
    • Very little Android specific logic is present in the main extension code.
    • When no Android specific properties are set, the extension works exactly as before.
  • Core functionalities, such as the ADB and JDWP clients, do not depend on VS Code and can be executed and tested outside VS Code.
  • Android support only concerns the launch mode, not the attach mode.
  • GitHub - gmondada/llvm-project at gab/lldb-dap-android

Future improvements

  • The extension does not start an Android emulator or the ADB server automatically. This could be added in the future, but it would create a dependency on the Android SDK.
  • The Swift extension, not to be confused with the LLDB DAP extension, automatically detects a Swift package and generates the launch.json file. It would be useful to detect Android projects and generate the launch.json file accordingly.
  • With the current solution, LLDB has to pull all shared objects from the target. By specifying the path to the APK in the launch.json file, LLDB could have a direct and faster access to all data.

Alternative solutions

  • Some logic could be moved to the C++ adapter, making it available in environments other than VS Code. Adopting the current solution does not prevent progressively moving functionalities into the adapter if this is the preferred direction.
  • A separate VS Code extension for Android could be created, relying on the LLDB DAP extension. The feasibility would need to be evaluated. LLDB-DAP would likely need to expose additional functionalities to be driven by another extension. Deployment and distribution of this new extension would also need to be discussed.

Work to be done before a PR

  • Ensure the solution works on macOS, Linux, and Windows
  • Ensure the solution works with different versions of the NDK
  • Ensure the solution works with different versions of Android
  • A few other minor fixes in the code
  • A test environment
  • Documentation
4 Likes

Thanks for the write up and was great to meet you at FOSDEM! As was discussed the next steps for Swift debugging in VS Code would be to get your proposed android changes in front of the lldb-dap community via their discord. There are some existing approaches to android I believe so it would be good to co-ordinate on those, and @JDevlieghere has offered to help navigate that community. Keep us posted how it goes and if any changes are also needed for the swiftlang.swift-vscode extension

2 Likes

About adding Android support in the LLDB-DAP VS Code extension, I'm moving the discussion to [RFC] Android support in LLDB-DAP VS Code extension - LLDB - LLVM Discussion Forums

Project update

All issues listed above have been addressed, and their fixes will be part of the Swift 6.3 release. They are also availabe in Swift toolchain development snapshots, starting from 2026-02-27.

We will probably discover new issues along the way, but debugging Swift on Android now works reasonably well, from the command line or with VS Code. See more details here.

Additionally, you can now try the experimental version of the LLDB DAP extension for VS Code that makes Swift debugging on Android much simpler.

As mentioned in my initial post above, the official LLDB DAP extension works well. However, for remote debugging (as required on Android), configuring and running a session requires many manual steps, which makes the solution cumbersome. This experimental version aims to automate most of these steps and make the user experience much simpler.

Install the VS Code extension

To build and install the extension, you need node and npm installed. Then run the following commands:

git clone --depth 1 --single-branch --branch gab/lldb-dap-android https://github.com/gmondada/llvm-project.git
cd llvm-project/lldb/tools/lldb-dap/extension
npm install
npm run compile
npm run package
npm run vscode-install

After that, restart VS Code.

Note: if you already had the LLDB DAP extension installed, it will be replaced by this experimental version. This version is compatible with the official one, so you do not lose any features.

Configuration

The extension uses lldb-dap, an executable provided with the Swift toolchain. You need to set its path in .vscode/settings.json:

{
  "lldb-dap.executable-path": "xxx/usr/bin/lldb-dap"
}

Replace xxx with the path to your toolchain. If you don’t know it, run:

swiftly use --print-location

Then you need to provide the ID of the app you want to debug. Create or edit .vscode/launch.json and add:

{
  "configurations": [
    {
      "type": "lldb-dap",
      "request": "launch",
      "name": "My App",
      "androidComponent": "org.example.helloswift/.MainActivity"
    }
  ]
}

Replace org.example.helloswift with your app ID.

Build and install the app

Before debugging, you need to connect an Android device or run an emulator, and it must be accessible via ADB. The extension cannot start the emulator or ADB for you yet.

Then, you need to build and install the app. If your project uses Gradle, run:

./gradlew assembleDebug
./gradlew installDebug -Pandroid.injected.testOnly=true

In theory, you could just run ./gradlew installDebug, but due to a bug in lldb-server (see [lldb][lldb-server] Fix zip file lookup ignoring last entry in the zip file by gmondada · Pull Request #173966 · llvm/llvm-project · GitHub ), we need to make sure the last entry in the APK is not a shared object. These two commands do the trick.

Run the debug session

In VS Code, set breakpoints in your Swift code, then go to the Debug tab and start the session with the :play_button: button (or press F5). That's it.

Additional options

The extension needs access to the Android NDK. In particular, it uses lldb-server provided with the NDK. If the Android SDK is installed in its default location and the NDK is installed as part of the SDK, the extension should find lldb-server automatically.

If not, you can set the path to the NDK in .vscode/settings.json:

{
  "lldb-dap.executable-path": "xxx/usr/bin/lldb-dap",
  "lldb-dap.androidNDKPath": "/Users/me/Library/Android/sdk/ndk/27.1.12297006"
}

If you have multiple devices connected, you can specify the target device in .vscode/launch.json:

{
  "configurations": [
    {
      "type": "lldb-dap",
      "request": "launch",
      "name": "My App",
      "androidComponent": "org.example.helloswift/.MainActivity",
      "androidDevice": "emulator-5554"
    }
  ]
}

Enjoy, and feel free to share your feedback.

2 Likes