Debugging app's native code - flutter-tizen/flutter-tizen GitHub Wiki
Your app may contain some native (C/C++) source code if the app language is C++ or if it depends on one or more native plugins. A source-level debugger like GDB/LLDB can be used to debug your native code, e.g. by setting breakpoints and examining variables.
Note: If you want to debug your app's Dart code but not the native code, you may want to read Debugging apps.
Device type
GDB | LLDB | Remarks | |
---|---|---|---|
TV device | ❌ | ❌ | Except development boards |
Non-TV device (normal) | ✔️ | ❌ | |
Non-TV device (rooted) | ✔️ | ✔️ | Including Tizen emulators |
App language
GDB | LLDB | |
---|---|---|
C++ (native app) | ✔️ | ✔️ |
C# (.NET app) | ❌ | ✔️ |
Note that LLDB is applicable for local (CLI) debugging only and requires superuser privileges. If your app's current language is C#, you may (temporarily) switch the language to C++ to enable GDB support as follows:
# Go to the app project directory and back up the "tizen" directory.
$ mv tizen tizen_csharp
# Create the project again.
$ flutter-tizen create --tizen-language cpp .
Note: If your device is rooted, make sure to sdb root off
before proceeding.
-
Build an app that you want to debug in debug mode and install it on your device.
-
Start the app without a loader process using the
app_launcher -e
(orflutter-tizen run
) command.# Stop if already running. $ sdb shell app_launcher -k [APP_ID] # Start the app. $ sdb shell app_launcher -e [APP_ID]
Note: You can debug an already running app only if it was launched without a loader process. To always launch the app without loader process, set the
direct-launch
metadata value toyes
in yourtizen-manifest.xml
:<ui-application ...> <metadata key="http://tizen.org/metadata/direct-launch" value="yes"/> </ui-application>
Do not include this metadata when you create a release build of your app as it affects the startup performance of the app.
-
Go to the app project directory and run
flutter-tizen-gdb
.$ flutter-tizen-gdb gdbserver is listening for debug connection on port 37375. Available commands: r Run GDB client p Print launch.json configuration v Open this project in VS Code q Quit
Note: Python 3.6 or above is required to run
flutter-tizen-gdb
. If you are on Windows, you can use thepython3
command to run the script (flutter-tizen/bin/flutter-tizen-gdb
) directly.If successful, you will see a message saying that gdbserver is listening for a debug connection. You can start GDB either from the command line (for CLI debugging) or by using VS Code's built-in debugger (for GUI debugging) to connect to the gdbserver.
Entering the r
command will open a GDB client process in the same window. Once a debug session is started, you can start debugging by typing any GDB command (such as bt
and b
) in the debugger console.
Enter a command: r
...
Reading /lib/ld-linux.so.3 from remote target...
0xf7435038 in ?? () from target:/lib/libc.so.6
Reading symbols from target:/lib/libc.so.6...
Reading /lib/libc-2.24.so.debug from remote target...
...
Reading symbols from target:/opt/usr/globalapps/com.example.my_app/bin/../lib/libflutter_plugins.so...
Reading symbols from target:/opt/usr/globalapps/com.example.my_app/bin/../lib/libflutter_engine.so...
(No debugging symbols found in target:/opt/usr/globalapps/com.example.my_app/bin/../lib/libflutter_engine.so)
(gdb)
-
Enter the
p
command to display a recommended VS Code debug configuration that looks like:{ "version": "0.2.0", "configurations": [ { "name": "flutter-tizen: gdb", "request": "launch", "type": "cppdbg", "externalConsole": false, "MIMode": "gdb", "symbolLoadInfo": { "loadAll": false, "exceptionList": "libc.so;libflutter*" }, "cwd": "path_to_app", "program": "path_to_runner", "miDebuggerPath": "path_to_gdb", "miDebuggerServerAddress": ":debug_port" } ] }
-
Launch VS Code and install the C/C++ extension if it's not already installed.
-
Open the app project folder (or add to the workspace).
-
Click the Run and Debug icon in the left menu bar, and click create a launch.json file to create a
launch.json
file for your project. Click the ⚙️ button if the file already exists. -
Replace the content of the file with the debug configuration you obtained in the above.
-
Make sure flutter-tizen: gdb is now selected as the active debug configuration.
-
Click the Run (▷) button or press
F5
to start debugging. Once a debug session is started, the Debug toolbar will appear at the top of the editor. (It may take a while for the debugger to connect to the remote gdbserver depending on your connection speed.)
If you want to set breakpoints or run GDB commands before your app starts, you have to manually configure gdbserver as follows.
-
Forward free ports for use by GDB and gdbserver. We'll use
29991
in this example.$ sdb forward tcp:29991 tcp:29991
-
Close the target app if it's already running, and launch the app under gdbserver using the
sdb launch
command.$ sdb launch -a "com.example.my_app" -p -e -m debug -P 29991 ... successfully launched pid = 29707 with debug 0
Press
Ctrl
+C
if the command doesn't automatically return.Caution: Make sure to enclose the app ID with quotation marks (
""
). -
Run
flutter-tizen-gdb
with the-p
(debug port) option.$ flutter-tizen-gdb -p 29991
-
Start a debug session either from the command line or from VS Code. You can enter
c
to resume the app from the paused state.0xb774fae0 in ?? () from target:/lib/ld-linux.so.2 (gdb) b OnResume Breakpoint 1 at 0x8008cdea: file flutter_app.cc, line 58. (gdb) c ... Thread 1 hit Breakpoint 1, FlutterApp::OnResume (this=0xbf9dba18) at flutter_app.cc:58 (gdb) bt
-
No response after attach
$ flutter-tizen-gdb pkg api_version: 4.0 Attached; pid = 7924
Maybe another app is being debugged on the same device. Stop all running apps (you can check with
app_launcher -S
) and launch the target app (app_launcher -e
) again. -
No loaded shared libraries match the pattern
Remote debugging using :29991 Reading /lib/ld-linux.so.3 from remote target... warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead. Reading /lib/ld-linux.so.3 from remote target... 0xf69dc038 in ?? () No loaded shared libraries match the pattern `libc.so'. No loaded shared libraries match the pattern `libflutter*'. (gdb) info share From To Syms Read Shared Object Library 0xf7341840 0xf735c990 No target:/lib/ld-linux.so.3 (gdb)
The app has been launched from a loader process. Restarting the app (
app_launcher -e
) will fix the problem. -
Connection reset by peer (or Remote connection closed)
Remote debugging using :29991 Remote communication error. Target disconnected.: Connection reset by peer. No loaded shared libraries match the pattern `libc.so'. No loaded shared libraries match the pattern `libflutter*'. (gdb)
gdbserver failed to attach to the app. Restarting the app (
app_launcher -e
) may fix the problem. -
Cannot insert breakpoint (or ERROR: Command aborted in VS Code Debug Console)
(gdb) b OnResume Breakpoint 1 at 0x4820: file flutter_app.cc, line 57. (gdb) c Continuing. Warning: Cannot insert breakpoint 1. Cannot access memory at address 0x4820 Command aborted. (gdb)
... Loaded 'target:/usr/lib/driver/libGLESv1_CM.so'. Cannot find or open the symbol file. Loaded 'target:/usr/lib/driver/libGLESv2.so'. Cannot find or open the symbol file. ERROR: Command aborted. See the output window for additional details. Execute debugger commands using "-exec <command>", ...
The runner's ELF format doesn't match the debugger's target system type. Build and install the app again.
-
received signal SIGABRT (or SIGSEGV)
Continuing. Thread 13 received signal SIGABRT, Aborted. [Switching to Thread 8777.8792] 0xf70c7e98 in ?? () from target:/lib/libc.so.6 (gdb)
Restarting the app may fix the problem. If the problem persists, please file an issue in this repository.
Note: LLDB is only available for rooted devices (such as a mobile emulator).
-
Download the LLDB RPM package for your target device from the Tizen package repository. For example, if your device is a mobile 6.5 emulator, you should download the
lldb-5.0.2-*.i686.rpm
file from Tizen 6.5 base packages for i686. -
Install the downloaded package to the device.
$ sdb root on $ sdb push [.rpm] /tmp $ sdb shell bash-3.2# mount -o remount,rw / bash-3.2# rpm -Uvh --force /tmp/[.rpm] bash-3.2# rm /tmp/[.rpm]
Note: You can also use GDB instead of LLDB if you prefer. You need to install all dependent packages (libpython
, db4
, and python
) before installing the GDB RPM package.
-
Build and run your app in debug mode.
-
Find the process ID (PID) of the running app. In the following example, the PID is
6691
.bash-3.2# app_launcher -S appId (PID) ... com.example.my_app (6691)
-
Attach LLDB to the running app using the PID.
bash-3.2# lldb -p [PID]
You can now start debugging by typing any LLDB command (such as
bt
andb
) in the debugger console. If you're not familiar with LLDB and LLDB commands, see the GDB to LLDB command map.
-
A dump file will be created in
/opt/usr/share/crash/dump
after your app crashes. Extract a.coredump
file from the zipped archive. For example,bash-3.2# cd /home/owner/share bash-3.2# unzip /opt/usr/share/crash/dump/com.example.my_app_6691_20220102060030.zip bash-3.2# cd com.example.my_app_6691_20220102060030 bash-3.2# tar -xf com.example.my_app_6691_20220102060030.coredump.tar
-
Open the core dump (
.coredump
) with LLDB.bash-3.2# lldb /opt/usr/globalapps/com.example.my_app/bin/runner -c com.example.my_app_6691_20220102060030.coredump (lldb) target create "/opt/usr/globalapps/com.example.my_app/bin/runner" --core "com.example.my_app_6691_20220102060030.coredump" Core file '/home/.../com.example.my_app_6691_20220102060030.coredump' (i386) was loaded. (lldb) bt * thread #1, name = 'runner', stop reason = signal SIGSEGV * frame #0: 0xb76f2a49 [vdso]`__kernel_vsyscall + 9 frame #1: 0xb755bb96 libc.so.6`___lldb_unnamed_symbol204$$libc.so.6 + 214 ...
Note: If you can't see any symbols from the backtrace (as shown below), it is likely that the crashed app was launched from a loader process. Make sure to always launch your app without a loader process (
app_launcher -e
).(lldb) bt * thread #1, name = 'runner', stop reason = signal SIGSEGV * frame #0: 0xb771ea49 frame #1: 0xbff39a4c
Engine and embedder symbols are stripped out and therefore not shown in the backtrace by default. If you want to load symbols of the engine (libflutter_engine.so
) or embedder (libflutter_tizen*.so
) during debugging, follow the instructions below.
-
Download embedder symbols that match the architecture of your device by running the following command.
$ flutter-tizen-gdb --download-symbols Downloading tizen-5.5-x86_symbols... Done Downloading tizen-6.5-x86_symbols... Done The downloaded symbols can be found at "symbols/".
Engine symbols can be manually downloaded from https://github.com/flutter-tizen/engine/releases. Note that the engine symbols cannot be loaded during remote debugging via gdbserver (due to the compiler and debugger version mismatch). Engine symbols can only be resolved during local debugging with LLDB.
-
If you're debugging with LLDB, copy the downloaded symbols to the device's
/tmp
directory. Skip this step if you're debugging with gdbserver.$ sdb push symbols/tizen-5.5-x86/libflutter_*.so /tmp
Choose
tizen-5.5
unless your app is targeting Tizen 6.5 or higher. -
Load the symbols. (Replace
_mobile
with your device's profile.)(gdb) add-symbol-file /path/to/libflutter_tizen_mobile.so Reading symbols from ... or (lldb) add-dsym /tmp/libflutter_tizen_mobile.so symbol file '/tmp/libflutter_tizen_mobile.so' has been added to ...
If you're debugging with gdbserver, you can just use the host file system paths to locate the symbol files. Otherwise, use the absolute paths to the symbol files you copied in the previous step.
-
Symbols for system libraries are available from the Tizen package repository. For example, if you have downloaded and installed the
ecore-core-debuginfo
debug package, you can load it into LLDB using theadd-dsym
command as follows.(lldb) add-dsym /usr/lib/debug/usr/lib/libecore.so.1.25.0.debug
-
Released symbols that are available for download contain limited debug information (g0) which may not be sufficient for general purpose debugging. You may want to build the engine or embedder from source to generate additional debug information (
g2
). You need to modifybuild/config/compiler/BUILD.gn
(engine) orbuild/config/BUILDCONFIG.gn
(embedder) as follows before running the build.@@ -907,6 +903,6 @@ config("minimal_symbols") { config("no_symbols") { if (!is_win) { - cflags = [ "-g0" ] + cflags = [ "-g2" ] } }
@@ -7,7 +7,7 @@ declare_args() { # 2 means regular build with symbols. # 1 means minimal symbols, usually enough for backtraces only. # 0 means no symbols. - symbol_level = 1 + symbol_level = 2 # Unoptimized build (a.k.a. debug build). is_unopt = false
Unstripped binaries can be found in the
so.unstripped
directory of the build directory after the build. -
If the
add-symbol-file
command does not automatically resolve the base addresses of the loaded shared libraries, you can manually find the addresses using theinfo share
command. In the following example, the addresses are0xb53ee540
and0xb74d7030
.(gdb) info share 0xb53ee540 0xb5fe6719 Yes (*) target:/opt/usr/globalapps/com.example.my_app/lib/libflutter_engine.so 0xb74d7030 0xb7537b79 Yes (*) target:/opt/usr/globalapps/com.example.my_app/lib/libflutter_tizen_mobile.so
You can pass these addresses to the
add-symbol-file
command.(gdb) add-symbol-file /path/to/libflutter_engine.so 0xb53ee540 (gdb) add-symbol-file /path/to/libflutter_tizen_mobile.so 0xb74d7030