diff --git a/README.md b/README.md
index 8fff2741..34b77c90 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,9 @@ The build instructions include instructions assuming that the [ninja-build](http
- flex
- bison
+**Android**
+ - Android NDK r18b or newer (https://developer.android.com/ndk/downloads)
+
### Building with CMake + Ninja
> **Windows Only**
@@ -41,13 +44,21 @@ ninja -C out
### Compiling for Android
For Android native debugging, it is possible to build ds2 with the Android NDK.
+An NDK version of at least r18b is required for C++17 support.
+
+CMake will automatically find the installed Android NDK if either the
+`ANDROID_NDK_ROOT` or `ANDROID_NDK` environment variable is set. Alternatively,
+the NDK location can be provided to CMake directly with the `CMAKE_ANDROID_NDK`
+variable, e.g. `-DCMAKE_ANDROID_NDK=/home/user/Android/Sdk/ndk/26.1.10909125`.
+To build for Android:
```sh
-cmake -B out -D CMAKE_SYSTEM_NAME=Android -D CMAKE_ANDROID_ARCH_ABI=armeabi-v7a -G Ninja -S ds2
-ninja -C out
+cd ds2
+cmake -B out -S . -D CMAKE_SYSTEM_NAME=Android -D CMAKE_ANDROID_ARCH_ABI=arm64-v8a -D CMAKE_BUILD_TYPE=Release -G Ninja
+cmake --build out
```
-Note that this will build ds2 targeting the highest level API level that the
+By default, CMake will build ds2 targeting the highest level API level that the
NDK supports. If you want to target another api level, e.g. 21, add the flag
`-DCMAKE_SYSTEM_VERSION=21` to your CMake invocation.
@@ -67,39 +78,125 @@ make
This will generate a binary that you can copy to your device to start
debugging.
+## Running ds2
+### Running on a remote host
-## Running ds2
+Launch ds2 in platform mode (not supported on Windows):
+```sh
+$ ./ds2 platform --server --listen localhost:4242
+```
-### Example
+Launch ds2 as a single-instance gdb server debugging a program:
+```sh
+$ ./ds2 gdbserver localhost:4242 /path/to/executable
+```
-#### On the remote host
+In both cases, ds2 is ready to accept connections on port 4242 from lldb.
-Launch ds2 with something like:
+### Running on an Android device
- $ ./ds2 gdbserver localhost:4242 /path/to/TestSimpleOutput
+When debugging Android NDK programs or applications, an Android device or
+emulator must be must be connected to the host machine and accessible via `adb`:
+```sh
+$ adb devices
+List of devices attached
+emulator-5554 device
+```
-ds2 is now ready to accept connections on port 4242 from lldb.
+To use ds2 on the Android target, copy the locally build ds2 binary to the
+`/data/local/tmp` directory on the Android target using `adb push` and launch it
+from there:
+```sh
+$ adb push build/ds2 /data/local/tmp
+$ adb shell /data/local/tmp/ds2 platform --server --listen *:4242
+```
-#### On your local host
+> [!NOTE]
+> If built on a Windows host, the ds2 executable file must also be marked
+> executable before launching it:
+> ```sh
+> $ adb shell chmod +x /data/local/tmp/ds2
+> ```
+
+The port that ds2 is listening on must be forwarded to the connected host
+using `adb forward`:
+```sh
+$ adb forward tcp:4242 tcp:4242
+```
- $ lldb /path/to/TestSimpleOutput
- Current executable set to '/path/to/TestSimpleOutput' (x86_64).
- (lldb) gdb-remote localhost:4242
- Process 8336 stopped
- * thread #1: tid = 8336, 0x00007ffff7ddb2d0, name = 'TestSimpleOutput', stop reason = signal SIGTRAP
- frame #0: 0x00007ffff7ddb2d0
- -> 0x7ffff7ddb2d0: movq %rsp, %rdi
- 0x7ffff7ddb2d3: callq 0x7ffff7ddea70
- 0x7ffff7ddb2d8: movq %rax, %r12
- 0x7ffff7ddb2db: movl 0x221b17(%rip), %eax
- (lldb) b main
- Breakpoint 1: where = TestSimpleOutput`main + 29 at TestSimpleOutput.cpp:6, address = 0x000000000040096d
- [... debug debug ...]
- (lldb) c
- Process 8336 resuming
- Process 8336 exited with status = 0 (0x00000000)
- (lldb)
+When debugging an Android application, the ds2 binary must be copied from
+`/data/local/tmp` into the target application's sandbox directory. This can be
+done using Android's `run-as` command:
+```sh
+$ adb shell run-as com.example.app cp /data/local/tmp/ds2 ./ds2
+$ adb shell run-as com.example.app ./ds2 platform --server --listen *:4242
+```
+
+> [!NOTE]
+> When running in an Android application's sandbox, the target application must
+> have internet permissions or ds2 will fail to open a port on launch:
+> ```xml
+>
+>
+> ```
+
+### Run lldb client on the local host
+
+#### Platform Mode
+If ds2 was launched in `platform` mode (not supported on Windows), lldb can
+connect to it using `platform` commands.
+
+For a remote Linux host:
+```
+$ lldb
+(lldb) platform select remote-linux
+(lldb) platform connect connect://localhost:4242
+```
+
+For a remote Android host:
+```
+$ lldb
+(lldb) platform select remote-android
+(lldb) platform connect connect://localhost:4242
+(lldb) platform settings -w /data/local/tmp
+```
+
+> [!NOTE]
+> When running in an Android application's sandbox, the `platform settings -w`
+> command, which sets the working directory, is not necessary because the
+> it is already set to the root of the application's writable sandbox directory.
+
+Once connected in platform mode, you can select the program to be run using the
+`file` command, run, and debug.
+```
+(lldb) file /path/to/executable
+(lldb) b main
+(lldb) run
+```
+
+#### Gdb Server Mode
+If ds2 was launched in `gdbserver` mode, lldb can connect to it with the
+`gdb-remote` command:
+```
+$ lldb /path/to/executable
+Current executable set to '/path/to/executable' (x86_64).
+(lldb) gdb-remote localhost:4242
+Process 8336 stopped
+* thread #1: tid = 8336, 0x00007ffff7ddb2d0, name = 'executable', stop reason = signal SIGTRAP
+ frame #0: 0x00007ffff7ddb2d0
+-> 0x7ffff7ddb2d0: movq %rsp, %rdi
+ 0x7ffff7ddb2d3: callq 0x7ffff7ddea70
+ 0x7ffff7ddb2d8: movq %rax, %r12
+ 0x7ffff7ddb2db: movl 0x221b17(%rip), %eax
+(lldb) b main
+Breakpoint 1: where = executable`main + 29 at test.cpp:6, address = 0x000000000040096d
+[... debug debug ...]
+(lldb) c
+Process 8336 resuming
+Process 8336 exited with status = 0 (0x00000000)
+(lldb)
+```
### Command-Line Options