Debugging

Code in Faasm has been cross-compiled to WebAssembly, so we lose a lot of debugging information. However, there are still some options for chasing down issues.

gdb

This project contains a default .gdbinit file to set some defaults for using gdb (e.g. disabling the segfault signal handling which is used by Faabric to do dirty tracking).

This is configured by default in the CLI container.

Backtrace

If you’re seeing a failure nested somewhere deep in an application but can’t work out how it’s getting there, you can use the __faasm_backtrace function to tell the runtime to print the stacktrace at any point in your code.

This can be very useful for debugging issues with Python C-extensions.

If you can locate the line where the problem might occur, e.g.

void someDeeplyNestedFunction() {
    // The line that you know has a problem
}

You can change this to:

extern "C" {
#include <faasm/host_interface.h>
}

void someDeeplyNestedFunction() {

    __faasm_backtrace(0);

    // The line that you know has a problem
}

Note that the line numbers in the stacktrace won’t match up to the original source, so you’ll just need to grep for it.

WAVM function symbols

WAVM assigns certain functions names like functionDef123, and we need to map these back to the original source to understand the output of a debugger.

To do this:

inv dev.cc func_sym
inv disas.symbols <user> <func>

This will output a mapping from names like functionDef123 to the names of functions as they appear in the source.

The output will appear at ${FAASM_LOCAL_DIR}/wasm/<user>/<function>/function.symbols.

GDB

We can use gdb normally on the func_runner target, e.g.

inv dev.cc func_runner
gdb func_runner

break functionDef123

run <user> <func>

Note that because the function itself is loaded using LLVM JIT libraries, GDB doesn’t have the symbols up front, but we can still set breakpoints pending a shared library load.

Debugging SGX

To debug SGX applications, you may need the sgx-gdb debugger to see the function symbols.