Debugging Rust code on mobile devices requires leveraging the native toolchains of your target platform (Android NDK or iOS Xcode) rather than relying solely on standard cargo commands. You typically build a debug binary with cargo using specific target triples, deploy it to the device, and attach a debugger like lldb or gdb to inspect the running process, often utilizing rust-lldb for better symbol resolution.
For Android, the most effective workflow involves building with the aarch64-linux-android target and using the Android Debug Bridge (ADB) to push the binary and attach lldb. Ensure you compile with debug symbols (--release strips them) and set RUST_BACKTRACE=1 for stack traces if the app crashes before you can attach.
# Build for Android with debug symbols
cargo build --target aarch64-linux-android --debug
# Push binary to device (assuming it's in target/aarch64-linux-android/debug)
adb push target/aarch64-linux-android/debug/my_app /data/local/tmp/my_app
# Run on device in background
adb shell /data/local/tmp/my_app &
# Attach lldb to the process
adb shell ps | grep my_app # Get PID
adb shell lldb -p <PID>
Once attached in lldb, use rust-lldb commands like bt (backtrace) or frame variable to inspect Rust types. If you are using a framework like flutter_rust_bridge or tauri-mobile, ensure the bridge is configured to pass debug symbols through the native layer.
For iOS, the process is tightly integrated with Xcode. You must build the Rust library as a static or dynamic framework using cargo-lipo or cargo-ndk (for cross-compilation) and link it into your Xcode project. Xcode's debugger handles the symbolication automatically if you include the .dSYM files generated during the Rust build.
# Build for iOS (requires Xcode installed and correct target)
cargo build --target aarch64-apple-ios --debug
# In Xcode:
# 1. Add the .dylib or .a file to your project
# 2. Set "Debug Information Format" to "DWARF with dSYM File" in Build Settings
# 3. Run the app and use the standard Xcode debugger (lldb)
# 4. Use 'po' (print object) or 'frame variable' to inspect Rust structs
Common pitfalls include missing debug symbols due to aggressive optimization or stripping, and mismatched target architectures. Always verify your target triple matches the device (e.g., aarch64 for modern phones, not x86_64 unless using an emulator). If you encounter "no debug info" errors, check that your Cargo.toml isn't forcing opt-level = 3 in the [profile.dev] section and that you haven't manually stripped the binary. For complex UI issues, combine native debugging with platform-specific tools like Android Studio's Layout Inspector or Xcode's View Debugger, as Rust usually handles the logic layer while the UI framework renders the view.