Skip to content

Commit 92c0916

Browse files
committed
docs: restructure tree
Introduce a new Documentation directory and move the Android documentation to it. This helps keep the tree organised and the top level directory feel less cluttered.
1 parent 75271f5 commit 92c0916

File tree

1 file changed

+172
-172
lines changed

1 file changed

+172
-172
lines changed
+172-172
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,172 @@
1-
# Debugging Android apps using lldb and ds2
2-
3-
ds2 can run as a debug server on an Android device or emulator to enable remote debugging of native
4-
code in Android applications. While ds2 is capable of connecting to gdb, this guide will focus on
5-
using [lldb](https://lldb.llvm.org/).
6-
7-
## Setup
8-
9-
### Installing adb
10-
Debugging Android requires the [Android Debug Bridge (adb)](https://developer.android.com/tools/adb)
11-
be installed on your workstation. It comes as part of the Android SDK Platform Tools, which can be
12-
downloaded [here](https://developer.android.com/tools/releases/platform-tools#downloads) without
13-
installing Android Studio.
14-
15-
### Enable Device Debugging
16-
If you are using a physical Android device, debugging must be enabled via the device's
17-
[developer options](https://developer.android.com/studio/debug/dev-options).
18-
19-
This step is unnecessary if you are using an Android emulator.
20-
21-
### Make the Application Debuggable
22-
The Android application you intend to debug must have `andriod:debuggable="true"` in its
23-
`AndroidManifest.xml` file:
24-
```xml
25-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
26-
...
27-
<application
28-
android:debuggable="true"
29-
...
30-
31-
```
32-
While the property can be set directly, it is typically set via a debug
33-
[build variant](https://developer.android.com/build/build-variants).
34-
35-
### Grant the Application Network Permission
36-
The application you intend to debug must have the `android.permission.INTERNET` permission declared
37-
in its `AndroidManifest.xml` file:
38-
```xml
39-
<uses-permission android:name="android.permission.INTERNET" />
40-
```
41-
If your application does not have this permission, you cannot debug it using ds2.
42-
43-
This requirement is necessary because:
44-
1. ds2 must run in the context of an application's sandbox to debug the application
45-
2. When running in an application's sandbox, ds2 is limited to the set of permissions granted to
46-
that application
47-
3. ds2 connects to the debugger via a TCP connection, so it requires network access
48-
49-
There are no other permissions required for ds2 to debug an Android application.
50-
51-
## Running ds2
52-
53-
### Deploying ds2 to the Android device
54-
Use adb to deploy the ds2 binary from your workstation to the `/data/local/tmp` directory on your
55-
Android device:
56-
57-
```bash
58-
$ adb push /path/to/ds2 /data/local/tmp
59-
```
60-
> **_NOTE:_** For the Android emulator, copy the `x86_64` version of ds2. For an Android device,
61-
copy the `arm64-v8a` version.
62-
63-
Ensure the binary is executable using `chmod +x` in the device shell:
64-
```bash
65-
$ adb shell chmod +x /data/local/tmp/ds2
66-
```
67-
### Copying ds2 into your application's sandbox
68-
ds2 can be executed directly from its `/data/local/tmp` location to debug programs launched via
69-
`adb shell`. However, to debug processes in an Android application, ds2 must be run in the context
70-
of that application's sandbox using `run-as`.
71-
72-
Android applications can read from the `/data/local/tmp` directory, but, per security policy, they
73-
cannot execute progams from this location. To work-around this restriction, you must first copy the
74-
ds2 binary to the application's private storage using `run-as cp`:
75-
```bash
76-
$ adb shell run-as com.example.TestApp cp /data/local/tmp/ds2 ./
77-
```
78-
This command copies the ds2 executable to root of the application's working directory (e.g.
79-
`/data/user/0/com.example.TestApp`). Once copied, you can execute ds2 from this location to debug
80-
the application.
81-
82-
To confirm ds2 can run in the sandbox, execute it with no arguments using `run-as`:
83-
```
84-
$ adb shell run-as com.example.TestApp ./ds2
85-
Usage:
86-
./ds2 [v]ersion
87-
./ds2 [g]dbserver [options]
88-
./ds2 [p]latform [options]
89-
```
90-
### Port forwarding
91-
To connect the debugger from your workstation to an instance of ds2 running on your Android device,
92-
use adb's port forwarding to forward a TCP port to use for the connection:
93-
```bash
94-
$ adb forward tpc:5432 tcp:5432
95-
```
96-
The exact port number you choose doesn't really matter as long as it is not already in use. Make
97-
note of the port number since you will need it later.
98-
### Running ds2
99-
Launch ds2 on your Android device in "platform" mode. Tell it to listen on the same port number that
100-
you forwarded with adb.
101-
```bash
102-
$ adb shell run-as com.example.TestApp ./ds2 platform --server --listen *:5432
103-
```
104-
ds2 will now block waiting for an incoming connection from a debugger. If this command fails, make
105-
sure the application has network permission (see above) and that there isn't already an instance of
106-
ds2 running with the same port number.
107-
108-
## Debugging with lldb
109-
110-
### Connecting
111-
You are now ready to connect the debugger. Launch lldb from the command line:
112-
```bash
113-
$ lldb
114-
```
115-
From the `(lldb)` prompt, run `platform select remote-android`:
116-
```bash
117-
(lldb) platform select remote-android
118-
Platform: remote-android
119-
Connected: no
120-
```
121-
Connenct to the running ds2 instance using `platform connect connect://localhost:5432`, specifying
122-
the same port number that ds2 is listening on in the connect URI:
123-
```bash
124-
(lldb) platform connect connect://localhost:5432
125-
Platform: remote-android
126-
Triple: aarch64-unknown-linux-android
127-
OS Version: 34 (5.10.198-android13-4-00050-g12f3388846c3-ab11920634)
128-
Hostname: localhost
129-
Connected: yes
130-
WorkingDir: /data/user/0/com.example.TestApp
131-
Kernel: #1 SMP PREEMPT Mon Jun 3 20:51:42 UTC 2024
132-
```
133-
Note the `WorkingDir` value: it should be the root of your application's data directory.
134-
### Attaching to a process
135-
With a platform connection established between lldb and ds2, you can now attach the debugger to a
136-
running process using its process ID (pid). To determine the pid for the process you wish to debug,
137-
list the processes running in your applications' sandbox with `platform process list`:
138-
```bash
139-
(lldb) platform process list
140-
2 matching processes were found on "remote-android"
141-
142-
PID PARENT USER TRIPLE NAME
143-
====== ====== ========== ============================== ============================
144-
8298 8296 u0_a284 aarch64-unknown-linux-android ds2
145-
8883 1139 u0_a284 aarch64-unknown-linux-android app_process64
146-
```
147-
Because ds2 is running in your application's sandbox, this command will list only processes that
148-
are also running in the sandbox. You should see both the ds2 process and an application process for
149-
each of your application's running processes. If you only see ds2, make sure your application is
150-
is running and try again.
151-
152-
Once you know the pid for the process you wish to debug, use the `attach --pid` command to attach
153-
the debugger to it:
154-
```
155-
(lldb) attach --pid 8883
156-
Process 8883 stopped
157-
* thread #1, name = 'example.TestApp', stop reason = signal SIGSTOP
158-
frame #0: 0x00000072cc1cad28 libc.so`__epoll_pwait + 8
159-
libc.so`__epoll_pwait:
160-
-> 0x72cc1cad28 <+8>: cmn x0, #0x1, lsl #12 ; =0x1000
161-
0x72cc1cad2c <+12>: cneg x0, x0, hi
162-
0x72cc1cad30 <+16>: b.hi 0xc6530 ; __set_errno_internal
163-
0x72cc1cad34 <+20>: ret
164-
Executable module set to "/home/user/.lldb/module_cache/remote-android/.cache/00418409-0550-60A6-0094-DA0030D00989/app_process64".
165-
Architecture set to: aarch64-unknown-linux-android0
166-
(lldb)
167-
```
168-
This command spawns an additional ds2 instance (running in gdbserver mode) which attaches to the
169-
process and sets-up the debug session with lldb.
170-
171-
Once attached, you can debug the process with standard gdb and lldb commands. An lldb tutorial can
172-
be found at [llvm.org](https://lldb.llvm.org/use/tutorial.html).
1+
# Debugging Android apps using lldb and ds2
2+
3+
ds2 can run as a debug server on an Android device or emulator to enable remote debugging of native
4+
code in Android applications. While ds2 is capable of connecting to gdb, this guide will focus on
5+
using [lldb](https://lldb.llvm.org/).
6+
7+
## Setup
8+
9+
### Installing adb
10+
Debugging Android requires the [Android Debug Bridge (adb)](https://developer.android.com/tools/adb)
11+
be installed on your workstation. It comes as part of the Android SDK Platform Tools, which can be
12+
downloaded [here](https://developer.android.com/tools/releases/platform-tools#downloads) without
13+
installing Android Studio.
14+
15+
### Enable Device Debugging
16+
If you are using a physical Android device, debugging must be enabled via the device's
17+
[developer options](https://developer.android.com/studio/debug/dev-options).
18+
19+
This step is unnecessary if you are using an Android emulator.
20+
21+
### Make the Application Debuggable
22+
The Android application you intend to debug must have `andriod:debuggable="true"` in its
23+
`AndroidManifest.xml` file:
24+
```xml
25+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
26+
...
27+
<application
28+
android:debuggable="true"
29+
...
30+
31+
```
32+
While the property can be set directly, it is typically set via a debug
33+
[build variant](https://developer.android.com/build/build-variants).
34+
35+
### Grant the Application Network Permission
36+
The application you intend to debug must have the `android.permission.INTERNET` permission declared
37+
in its `AndroidManifest.xml` file:
38+
```xml
39+
<uses-permission android:name="android.permission.INTERNET" />
40+
```
41+
If your application does not have this permission, you cannot debug it using ds2.
42+
43+
This requirement is necessary because:
44+
1. ds2 must run in the context of an application's sandbox to debug the application
45+
2. When running in an application's sandbox, ds2 is limited to the set of permissions granted to
46+
that application
47+
3. ds2 connects to the debugger via a TCP connection, so it requires network access
48+
49+
There are no other permissions required for ds2 to debug an Android application.
50+
51+
## Running ds2
52+
53+
### Deploying ds2 to the Android device
54+
Use adb to deploy the ds2 binary from your workstation to the `/data/local/tmp` directory on your
55+
Android device:
56+
57+
```bash
58+
$ adb push /path/to/ds2 /data/local/tmp
59+
```
60+
> **_NOTE:_** For the Android emulator, copy the `x86_64` version of ds2. For an Android device,
61+
copy the `arm64-v8a` version.
62+
63+
Ensure the binary is executable using `chmod +x` in the device shell:
64+
```bash
65+
$ adb shell chmod +x /data/local/tmp/ds2
66+
```
67+
### Copying ds2 into your application's sandbox
68+
ds2 can be executed directly from its `/data/local/tmp` location to debug programs launched via
69+
`adb shell`. However, to debug processes in an Android application, ds2 must be run in the context
70+
of that application's sandbox using `run-as`.
71+
72+
Android applications can read from the `/data/local/tmp` directory, but, per security policy, they
73+
cannot execute progams from this location. To work-around this restriction, you must first copy the
74+
ds2 binary to the application's private storage using `run-as cp`:
75+
```bash
76+
$ adb shell run-as com.example.TestApp cp /data/local/tmp/ds2 ./
77+
```
78+
This command copies the ds2 executable to root of the application's working directory (e.g.
79+
`/data/user/0/com.example.TestApp`). Once copied, you can execute ds2 from this location to debug
80+
the application.
81+
82+
To confirm ds2 can run in the sandbox, execute it with no arguments using `run-as`:
83+
```
84+
$ adb shell run-as com.example.TestApp ./ds2
85+
Usage:
86+
./ds2 [v]ersion
87+
./ds2 [g]dbserver [options]
88+
./ds2 [p]latform [options]
89+
```
90+
### Port forwarding
91+
To connect the debugger from your workstation to an instance of ds2 running on your Android device,
92+
use adb's port forwarding to forward a TCP port to use for the connection:
93+
```bash
94+
$ adb forward tpc:5432 tcp:5432
95+
```
96+
The exact port number you choose doesn't really matter as long as it is not already in use. Make
97+
note of the port number since you will need it later.
98+
### Running ds2
99+
Launch ds2 on your Android device in "platform" mode. Tell it to listen on the same port number that
100+
you forwarded with adb.
101+
```bash
102+
$ adb shell run-as com.example.TestApp ./ds2 platform --server --listen *:5432
103+
```
104+
ds2 will now block waiting for an incoming connection from a debugger. If this command fails, make
105+
sure the application has network permission (see above) and that there isn't already an instance of
106+
ds2 running with the same port number.
107+
108+
## Debugging with lldb
109+
110+
### Connecting
111+
You are now ready to connect the debugger. Launch lldb from the command line:
112+
```bash
113+
$ lldb
114+
```
115+
From the `(lldb)` prompt, run `platform select remote-android`:
116+
```bash
117+
(lldb) platform select remote-android
118+
Platform: remote-android
119+
Connected: no
120+
```
121+
Connenct to the running ds2 instance using `platform connect connect://localhost:5432`, specifying
122+
the same port number that ds2 is listening on in the connect URI:
123+
```bash
124+
(lldb) platform connect connect://localhost:5432
125+
Platform: remote-android
126+
Triple: aarch64-unknown-linux-android
127+
OS Version: 34 (5.10.198-android13-4-00050-g12f3388846c3-ab11920634)
128+
Hostname: localhost
129+
Connected: yes
130+
WorkingDir: /data/user/0/com.example.TestApp
131+
Kernel: #1 SMP PREEMPT Mon Jun 3 20:51:42 UTC 2024
132+
```
133+
Note the `WorkingDir` value: it should be the root of your application's data directory.
134+
### Attaching to a process
135+
With a platform connection established between lldb and ds2, you can now attach the debugger to a
136+
running process using its process ID (pid). To determine the pid for the process you wish to debug,
137+
list the processes running in your applications' sandbox with `platform process list`:
138+
```bash
139+
(lldb) platform process list
140+
2 matching processes were found on "remote-android"
141+
142+
PID PARENT USER TRIPLE NAME
143+
====== ====== ========== ============================== ============================
144+
8298 8296 u0_a284 aarch64-unknown-linux-android ds2
145+
8883 1139 u0_a284 aarch64-unknown-linux-android app_process64
146+
```
147+
Because ds2 is running in your application's sandbox, this command will list only processes that
148+
are also running in the sandbox. You should see both the ds2 process and an application process for
149+
each of your application's running processes. If you only see ds2, make sure your application is
150+
is running and try again.
151+
152+
Once you know the pid for the process you wish to debug, use the `attach --pid` command to attach
153+
the debugger to it:
154+
```
155+
(lldb) attach --pid 8883
156+
Process 8883 stopped
157+
* thread #1, name = 'example.TestApp', stop reason = signal SIGSTOP
158+
frame #0: 0x00000072cc1cad28 libc.so`__epoll_pwait + 8
159+
libc.so`__epoll_pwait:
160+
-> 0x72cc1cad28 <+8>: cmn x0, #0x1, lsl #12 ; =0x1000
161+
0x72cc1cad2c <+12>: cneg x0, x0, hi
162+
0x72cc1cad30 <+16>: b.hi 0xc6530 ; __set_errno_internal
163+
0x72cc1cad34 <+20>: ret
164+
Executable module set to "/home/user/.lldb/module_cache/remote-android/.cache/00418409-0550-60A6-0094-DA0030D00989/app_process64".
165+
Architecture set to: aarch64-unknown-linux-android0
166+
(lldb)
167+
```
168+
This command spawns an additional ds2 instance (running in gdbserver mode) which attaches to the
169+
process and sets-up the debug session with lldb.
170+
171+
Once attached, you can debug the process with standard gdb and lldb commands. An lldb tutorial can
172+
be found at [llvm.org](https://lldb.llvm.org/use/tutorial.html).

0 commit comments

Comments
 (0)