Debugging an Application

Once an application has been built and installed, it may be necessary to debug it from within the sandbox where it runs. By default, each flatpak that is built has a corresponding .Debug runtime extension that provides debugging information for the application. This cannot be exported as a binary bundle in the same way as for application flatpaks, so we first need to find another way to install it.

Installing the Debug Package

In Installing from a Local Repository, we installed an application from a local repository by adding its repository to those registered with Flatpak on the system:

flatpak remote-add --no-gpg-verify my-local-repo myrepo

Once this repository has been added with the my-local-repo remote, we can list its contents:

flatpak remote-ls my-local-repo -a

The -a option ensures that the debug runtime extension is also listed. For the libhandy example we have been using, the above command produces this output:

Ref
sm.puri.Handy.Example
sm.puri.Handy.Example.Debug

We install the application from the repository in the normal way:

flatpak install my-local-repo sm.puri.Handy.Example

In addition to this, we install the debug runtime extension for the application:

flatpak install my-local-repo sm.puri.Handy.Example.Debug

This allows us to access debugging symbols in the sandbox.

Running a Debug Shell

A debugging environment can be created by starting a shell inside the sandbox:

flatpak run --devel --command=bash sm.puri.Handy.Example

The sandboxed shell will start running and will show a prompt like this:

bash-4.4$

From this point the application can be run as normal by running the example executable, either relying on the PATH environment variable or running it using its full path:

bash-4.4$ /app/bin/example

For some kinds of applications, simply being able to run the code from the command line in the sandbox is useful. However, when using compiled languages, you may need to perform lower level debugging.

Using GDB in the Sandbox

We can also run the application using gdb for debugging:

bash-4.4$ gdb /app/bin/example

So, for example, we could set a breakpoint on execution of the main function:

(gdb) b main
Breakpoint 1 at 0x3510
(gdb) r
Starting program: /app/bin/example

Although this is useful if we want to simply pause execution at a certain point, we need more information if we want to do more detailed debugging.

Running gdb again, we load the debugging symbols from the relevant file:

(gdb) symbol-file /app/lib/debug/bin/example.debug
Reading symbols from /app/lib/debug/bin/example.debug...done.

We can now set a breakpoint at the start of the main function and run the application:

(gdb) b main
Breakpoint 1 at 0x3650: file ../examples/example.c, line 33.
(gdb) r
Starting program: /app/bin/example

Breakpoint 1, main (argc=1, argv=0x7fffffffde98) at ../examples/example.c:33
33      {

With the debugging symbols loaded, once the breakpoint is reached we can list the source code for the function:

(gdb) l
28      }
29
30      int
31      main (int    argc,
32            char **argv)
33      {
34        GtkApplication *app;
35        int status;
36
37        hdy_init (&argc, &argv);

GDB can be used as normal to debug the application.

Further Reading

The Flatpak debugging documentation provides more ways to debug sandboxed applications.