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.

Support status

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 .

Remote debugging with GDB and gdbserver

Starting gdbserver

Note: If your device is rooted, make sure to sdb root off before proceeding.

  1. Build an app that you want to debug in debug mode and install it on your device.

  2. Start the app without a loader process using the app_launcher -e (or flutter-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 to yes in your tizen-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.

  3. 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 the python3 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.

a. Connecting from the command line

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)

b. Connecting from VS Code

  1. 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"
            }
        ]
    }
  2. Launch VS Code and install the C/C++ extension if it's not already installed.

  3. Open the app project folder (or add to the workspace).

  4. 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.

  5. Replace the content of the file with the debug configuration you obtained in the above.

  6. Make sure flutter-tizen: gdb is now selected as the active debug configuration.

    Debug configuration

  7. 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.)

Starting an app in a paused state

If you want to set breakpoints or run GDB commands before your app starts, you have to manually configure gdbserver as follows.

  1. Forward free ports for use by GDB and gdbserver. We'll use 29991 in this example.

    $ sdb forward tcp:29991 tcp:29991
  2. 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 ("").

  3. Run flutter-tizen-gdb with the -p (debug port) option.

    $ flutter-tizen-gdb -p 29991
  4. 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

Troubleshooting

  • 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.

Local debugging with LLDB

Note: LLDB is only available for rooted devices (such as a mobile emulator).

Installation

  1. 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.

  2. 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.

a. Live debugging

  1. Build and run your app in debug mode.

  2. 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)
  3. 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 and b) in the debugger console. If you're not familiar with LLDB and LLDB commands, see the GDB to LLDB command map.

b. Debugging core dumps

  1. 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
  2. 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

Resolving engine and embedder symbols

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.

  1. 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.

  2. 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.

  3. 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.

Resolving more symbols

  • 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 the add-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 modify build/config/compiler/BUILD.gn (engine) or build/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 the info share command. In the following example, the addresses are 0xb53ee540 and 0xb74d7030.

    (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
⚠️ **GitHub.com Fallback** ⚠️