Reputation: 1838
I've tried a number of ways to get this to work but to no avail so far. My requirements are as follows:
I'm aware that the gdb server must run on the device. A python script in the NDK (ndk-gdb) can copy this to the device and execute it, which then launches its own shell which can be used to set breakpoints, which is useful in a pinch but nowhere near as intuitive as a full GUI.
So, given that the gdb-server is now running on the device, I should be able to connect to it.
I'm trying to use this 'launch.json' debug config in vs-code:
{
"name": "Debug App on Device",
"type": "cppdbg",
"request": "launch",
"cwd": "${workspaceRoot}",
"program":"${workspaceRoot}\\android-build\\DebugSys\\system\\bin\\app_process64",
"additionalSOLibSearchPath": "${workspaceRoot}\\android-build\\obj\\local\\arm64-v8a",
"miDebuggerServerAddress": "192.168.1.121:5039",
"setupCommands": [{
"text": "set solib-absolute-prefix ${workspaceRoot}/android-build/",
"ignoreFailures": false
}],
"windows": {
"miDebuggerPath": "C:\\Users\\luthe\\AppData\\Local\\Android\\Sdk\\ndk\\23.1.7779620\\prebuilt\\windows-x86_64\\bin\\gdb.exe",
"MIMode": "gdb"
}
},
But running it gives me this error:
(No connection could be made because the target machine actively refused it).
This probably isn't a firewall issue as I'm able to connect to another server I have running, launched by the app in question on port 8080.
Is there an error in my 'launch.json' or am I going about all of this in entirely the wrong way. Also, would it make sense for my app to launch the gdb server instead or is it better/neutral to have ndk-gdb do it?
Upvotes: 2
Views: 3352
Reputation: 1838
In then end, I eschewed lldb in favour of gdb, which ndk-debug can use (for now, they're depreciating it, even though it works and lldb clearly either does not work or requires some setting that it doesn't advertise to work) if you include the 'no_lldb' flag or set 'use_lldb' to 'False' in ndk-gdb.py.
However, if you want visual debugging, you have to not let ndk-dbg.py launch the local gdb client. I've done this by creating a minimal batch file that connects to the phone and this may be useful for people reading this in the future in order to have a clear overview of what's happening on the android device and on the local machine. This script assumes only one device is attached for clarity.
adb shell forward tcp:5039 localfilesystem:/data/user/0/yourorg.yourapp/debug_socket #forward port 5039 to a temporary file called 'debug_socket'. I believe this is called is a 'Unix domain socket'
adb shell run-as yourorg.yourapp rm /data/user/0/yourorg.yourapp/debug_socket #remove the old socket file
adb push libs\arm64-v8a\gdbserver /data/local/tmp/arm64-gdbserver #push the arm64-gdbserver to a temp dir on the device
adb shell run-as yourorg.yourapp "cp /data/local/tmp/arm64-gdbserver /data/user/0/yourorg.yourapp/arm64-gdbserver" #copy the gdbserver to a directory from which it can be run with the privilages of the app you wish to debug
adb shell run-as yourorg.yourapp chmod 700 /data/user/0/yourorg.yourapp/arm64-gdbserver #Ensure 'arm64-gdbserver' is executable
adb shell run-as yourorg.yourapp /data/user/0/yourorg.yourapp/arm64-gdbserver --once +/data/user/0/yourorg.yourapp/debug_socket --attach 1234 #Run gdb server on device, connecting to the societ and the process '1234' (replace with actual PID of your running process)
Where 'yourorg.yourapp' is the name of your org and app and 1234 is the PID of the process to be debugged on your android device.
In visual studio code, you will need to have C++ extensions and gdb debugger extensions installed.
This is the 'launch.json' script that launches gdb locally and connects to the android device. Note that symbols are needed on the client side but not on the android device, so they can stripped if needed.
{
"name": "Debug pilkapel on device",
"type": "cppdbg",
"request": "launch",
"cwd": "${workspaceRoot}",
"program":"${workspaceRoot}\\android-build\\DebugSys\\system\\bin\\app_process64",
"additionalSOLibSearchPath": "${workspaceRoot}\\android-build\\obj\\local\\arm64-v8a",
"miDebuggerServerAddress": "localhost:5039",
"setupCommands": [
{
"text": "set solib-absolute-prefix ${workspaceRoot}/android-build/",
"ignoreFailures": true
}
],
"windows":
{
"miDebuggerPath": "C:\\Users\\luthe\\AppData\\Local\\Android\\Sdk\\ndk\\23.1.7779620\\prebuilt\\windows-x86_64\\bin\\gdb.exe",
"MIMode": "gdb"
}
}
Also, compiler flags are important for this! These are the compiler flags I used for the debug build of the library I'm working on:
LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS) -O0 -g -ggdb -gdwarf64
LOCAL_CPPFLAGS += -gfull -fstandalone-debug -Wl -gno-split-dwarf
LOCAL_CPPFLAGS += -fno-unique-internal-linkage-names -fno-direct-access-external-data
LOCAL_CPPFLAGS += -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes
LOCAL_CPPFLAGS += -Wformat -Werror=format-security -fno-limit-debug-info -fPIC
Some of these may be unnecessary for the task at hand, I did really quite a lot of iteration using lldb but nothing worked. For gdb, I believe it needs -gdwarf-5 as the debugging format (which I gather is the default). When I specified -gdwarf-4 as part of my experimentations, the gdb server ran but breakpoints did not work.
Upvotes: 1
Reputation: 1838
Ok, so I still can't debug but I can now at least run the debug server and connect to it. It seems there's a problem with my symbol file for my C++ .so library which I'm trying to resolve here
The process I've used to run this on the device is this:
adb shell forward tcp:5039 localfilesystem:/data/user/0/totga.anthracite/debug_socket
adb shell run-as totga.anthracite rm /data/user/0/totga.anthracite/debug_socket
adb shell run-as totga.anthracite /data/user/0/totga.anthracite/arm64-lldb-server gdbserver unix:///data/user/0/totga.anthracite/debug_socket --attach 1234
where '1234' is the process ID on the device
and 'totga.anthracite' is my package name. You need to copy the 'arm64-lldb-server' to the data directory indicated (I'd run this step beforehand) and also remember to delete the 'debug_socket' file - that was messing things up before.
On the VSCode side, add something like this to 'launch.json'
{
"name": "Debug android app on device",
"type": "cppdbg",
"request": "launch",
"cwd": "${workspaceRoot}",
"program":"${workspaceRoot}\\android-build\\DebugSys\\system\\bin\\app_process64",
"additionalSOLibSearchPath": "${workspaceRoot}\\android-build\\obj\\local\\arm64-v8a",
"miDebuggerServerAddress": "localhost:5039",
"setupCommands": [
{
"text": "set solib-absolute-prefix ${workspaceRoot}/android-build/",
"ignoreFailures": true
}
],
"windows": {
"miDebuggerPath": "${ANDROID_NDK_HOME}/prebuilt/windows-x86_64\\bin\\gdb.exe",
"MIMode": "gdb"
}
}
This should connect but, if like me you have no symbols, you still can't debug. Hopefully once that issue is resolved, this will work and I'll be able to debug native C++ code on an android device.
Upvotes: 0