How do I use lldb to debug C++ code on Android on command line
Asked Answered
S

3

6

How can I debug my Android NDK project in C++, using the lldb debugger from the command line?

Stoat answered 11/12, 2018 at 23:15 Comment(0)
P
8

Probably you can try below: (This example steps are based on macOS)

run gdb server and attach process

//Below commands will suspend the execution on the running app, and waits for a debugger to connect to it on port 5045.
adb shell

// to get pid
root@generic_x86:/ # ps | grep <your-app-name>
u0_a54    6510  1196  800157 47442 ffffffff b662df1b S 

<your-app-name>

root@generic_x86:/ # gdbserver :5045 --attach 6510 (PID)
Attached; pid = 6510
Listening on port 5045
//The process is now suspended, and gdbserver is listening for debugging clients on port 5045.

attach gdb debugger

//open a new terminal, e.g. terminal2, send below commands from this new terminal
//forward the above port to a local port on the host with the abd forward command
adb forward tcp:5045 tcp:5045
//launch gdb client from your android ndk folder
<your-ndk-home>/android-ndk-r16b/prebuilt/darwin-x86_64/bin/gdb
//Target the gdb to the remote sever
(gdb) target remote :5045

//now the process is successfully attached with the application for debugging, you can see below info from terminal 1.
Remote debugging from host 127.0.0.1
Pupa answered 12/12, 2018 at 2:2 Comment(7)
Thank you for your response, but this answer uses gdb, not lldbStoat
The lldb command equivalent to target remote :5045 is gdb-remote localhost:5045. lldb can talk to a generic gdbserver, so shizen's instructions should work fine, just replacing the gdb with the lldb command to connect.Skellum
Note: lldb also provides its own gdb remote protocol server (called unsurprisingly lldb-server). It isn't required, but does have some extensions lldb will use to debug more efficiently. Sadly, I don't know enough about Android distro's to know how you would get and install an appropriate version of lldb-server.Skellum
The shell command 'gdbserver :5045 --attach <mypid>' returns '/system/bin/sh: gdbserver: inaccessible or not found', presumably because I'm not rooted. Is there any way to do this without root? I've noticed that my Android Studio (3.5.2) doesn't seem to want to pause for LLDB debugger to attach when debugging instrumented tests. In fact it says 'starting LLDB server' forever, and won't let me cancel the operation. Given that bug, I was hoping to use the CLI directly but rooting my test device is not really an option.Guttery
I met the same issue, I wonder how Android studio started the lldb server at the device sideIerna
When target remote :5045, I have following error. Reading /system/bin/linker64 from remote target... /Users/daqi/Library/Android/sdk/ndk/22.0.7026061/prebuilt/darwin-x86_64/bin/gdb: line 3: 74796 Segmentation fault: 11 PYTHONHOME="$GDBDIR/.." "$GDBDIR/gdb-orig" "$@"Dissociation
If somebody is actually using gdb rather than lldb, you can use ndk-gdb by simply making a 1-line jni/Android.mk file adjacent to AndroidManifest.xml containing APP_ABI=all.Necker
M
11

1. Preparation

  • Prepare an android device(Root privilege is not required, we will use its /data/local/tmp directory).
  • Install NDK, CMake, Ninja, adb, lldb, and put them in PATH env var.

2. Compile program with debugging info (i.e. keep the -g flag)

After compilation, copy them to your device's /data/local/tmp directory.

3. Copy NDK provided lldb-server to device

Copy NDK provided lldb-server to your android phone(prefer the 64bit one),

adb push ./toolchains/llvm/prebuilt/windows-x86_64/lib64/clang/9.0.9/lib/linux/aarch64/lldb-server /data/local/tmp

and start it by:

./lldb-server platform --listen "*:10086" --server

10086 is port number, you may change it.

4. Forward port

Forward port by running:

adb forward tcp:10086 tcp:10086

5. Get device name

adb devices   #For me, it's 39688bd9

6. Install LLDB

Install LLDB, adding its binary to PATH, typing these commands:

platform select remote-android
platform connect connect://39688bd9:10086

Among whith, 39688bd9 is my device id, 10086 is the port that I choose in previous steps.

7. Use LLDB

Now, you're connected with lldb-server, thus just use lldb like locally:

file some_executable_file_with_debug_info
b main
r
Max answered 25/11, 2020 at 1:34 Comment(2)
I've been redirected here from: #72553530 and your suggestion works, but can you share any pointers about why it's device id but not localhost?Dogoodism
Correction: localhost also works, but 127.0.0.1 doesn't.Dogoodism
P
8

Probably you can try below: (This example steps are based on macOS)

run gdb server and attach process

//Below commands will suspend the execution on the running app, and waits for a debugger to connect to it on port 5045.
adb shell

// to get pid
root@generic_x86:/ # ps | grep <your-app-name>
u0_a54    6510  1196  800157 47442 ffffffff b662df1b S 

<your-app-name>

root@generic_x86:/ # gdbserver :5045 --attach 6510 (PID)
Attached; pid = 6510
Listening on port 5045
//The process is now suspended, and gdbserver is listening for debugging clients on port 5045.

attach gdb debugger

//open a new terminal, e.g. terminal2, send below commands from this new terminal
//forward the above port to a local port on the host with the abd forward command
adb forward tcp:5045 tcp:5045
//launch gdb client from your android ndk folder
<your-ndk-home>/android-ndk-r16b/prebuilt/darwin-x86_64/bin/gdb
//Target the gdb to the remote sever
(gdb) target remote :5045

//now the process is successfully attached with the application for debugging, you can see below info from terminal 1.
Remote debugging from host 127.0.0.1
Pupa answered 12/12, 2018 at 2:2 Comment(7)
Thank you for your response, but this answer uses gdb, not lldbStoat
The lldb command equivalent to target remote :5045 is gdb-remote localhost:5045. lldb can talk to a generic gdbserver, so shizen's instructions should work fine, just replacing the gdb with the lldb command to connect.Skellum
Note: lldb also provides its own gdb remote protocol server (called unsurprisingly lldb-server). It isn't required, but does have some extensions lldb will use to debug more efficiently. Sadly, I don't know enough about Android distro's to know how you would get and install an appropriate version of lldb-server.Skellum
The shell command 'gdbserver :5045 --attach <mypid>' returns '/system/bin/sh: gdbserver: inaccessible or not found', presumably because I'm not rooted. Is there any way to do this without root? I've noticed that my Android Studio (3.5.2) doesn't seem to want to pause for LLDB debugger to attach when debugging instrumented tests. In fact it says 'starting LLDB server' forever, and won't let me cancel the operation. Given that bug, I was hoping to use the CLI directly but rooting my test device is not really an option.Guttery
I met the same issue, I wonder how Android studio started the lldb server at the device sideIerna
When target remote :5045, I have following error. Reading /system/bin/linker64 from remote target... /Users/daqi/Library/Android/sdk/ndk/22.0.7026061/prebuilt/darwin-x86_64/bin/gdb: line 3: 74796 Segmentation fault: 11 PYTHONHOME="$GDBDIR/.." "$GDBDIR/gdb-orig" "$@"Dissociation
If somebody is actually using gdb rather than lldb, you can use ndk-gdb by simply making a 1-line jni/Android.mk file adjacent to AndroidManifest.xml containing APP_ABI=all.Necker
S
3

With android-ndk-r25b, I had some luck with the below:

In shell window 1

adb push <ndk_dir>/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/14.0.6/lib/linux/aarch64/lldb-server /data/local/tmp
adb shell chmod +x /data/local/tmp/lldb-server
adb shell run-as <package_name> killall -9 lldb-server
sleep 1
adb shell run-as <package_name> cp /data/local/tmp/lldb-server /data/data/<package_name>/
adb shell am start -D -n "<package_name>/android.app.NativeActivity"
adb shell run-as <package_name> sh -c '/data/data/<package_name>/lldb-server platform --server --listen unix-abstract:///data/data/<package_name>/debug.socket'"

In shell window 2

# Get the pid of the process you are trying to debug
adb shell run-as <package_name> ps
lldb
> platform select remote-android
> platform connect unix-abstract-connect:///data/data/<package_name>/debug.socket
> attach <pid>

In shell window 3

# You will again need the pid of the process you are trying to debug
adb shell run-as <package_name> ps
adb forward tcp:12345 jdwp:<pid>
jdb -attach localhost:12345

Then go back to lldb running in window 2, and continue your process

I found this script to be useful: https://github.com/iivke/flutter_android_lldb/blob/main/flutter_lldb.py

Schematize answered 2/12, 2022 at 20:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.