One of the great powers of namespace APIs on Linux (mount namespaces, user namespaces, etc) is that you can create a new view into the world of your computer that is very different from the host. This can make traditional profiling tools difficult.
To begin with, we need to ensure that we have access to
perf infrastructure. Easy enough, just don’t drop those privileges before calling
execve(). This is the
--allow=devel option to
flatpak run. But after that, we need to do the detailed phase of translating instruction pointers to a function name.
Generally, the translation between an instruction pointer and a function name requires looking up what file is mapped over the address. Then you open that file with an ELF reader and locate the file containing debug information (which may be the same file). Then open that file and locate what function contains that instruction pointer. (We subtract the beginning of the map from the instruction pointer to get a relative offset).
Now, here is the trouble with mount namespaces. The “path” of the map might be something like “
/newroot/usr/lib/libgtk-3.so“. Of course, “
/newroot/” doesn’t actually exist.
So… what to do.
Well, we can find information about the mounts in the process by looking at
/proc/$pid/mountinfo. Just look for the longest common prefix to get the translation from the mount namespace into the host. One caveat though. The translated path is relative to the root of the partition mounted. So the next step is to locate the file-system mount on the host (via
If you put this all together, you can profile and extract symbols from applications running inside of containers.
Now, most applications aren’t going to ship debug symbols with them. But we’ll need those for proper symbol extraction. So if you install the
.Debug variant of a Flatpak runtime (
org.gnome.Sdk.Debug for example) then we can setup symbol resolution specifically for
/usr/lib/debug. Builder now does this.
I’m not sure, but I think this makes Builder and Sysprof one of the first (if not the first) profiler on Linux to support symbol extraction while profiling containerized applications from outside the container.
I’ve only tested with Flatpak, but I don’t see why this code can’t work with other tooling using mount namespaces.