Debugging & Tracing
Relevant source files
The following files were used as context for generating this wiki page:
Debugging and tracing within AtomVM are critical systems designed to support development across highly constrained environments, ranging from microcontrollers like the ESP32 and STM32 to WebAssembly and Generic UNIX platforms. The system provides multiple layers of visibility, including compile-time instrumentation, runtime crash reporting, and hardware-level debugging interfaces.
The primary goal of the debugging infrastructure is to facilitate the "deploy, test, debug" lifecycle on hardware where traditional POSIX abstractions may be unavailable. Developers can leverage tools like serial consoles for log monitoring or JTAG for deep hardware inspection, while the VM itself can be configured to emit detailed execution traces and stack information.
Sources: doc/src/getting-started-guide.md:12-16, doc/src/welcome-to-atomvm.md:123-127
Architecture and Configuration
AtomVM utilizes a modular approach to debugging, where most tracing and diagnostic features are toggled at compile-time via CMake options. This allows developers to balance the need for diagnostic information against the strict memory constraints of target devices.
Compile-time Diagnostic Options
The core library, libAtomVM, defines several definitions that control the inclusion of debugging logic. These flags influence how the VM handles process failures, stack overflows, and execution tracing.
| Option | Definition | Description |
|---|---|---|
ADVANCED_TRACING | ENABLE_ADVANCED_TRACE | Enables deep execution tracing within the VM core. |
AVM_CREATE_STACKTRACES | AVM_CREATE_STACKTRACES | Enables the generation of stack traces for Erlang/Elixir processes. |
AVM_PRINT_PROCESS_CRASH_DUMPS | AVM_PRINT_PROCESS_CRASH_DUMPS | Forces the VM to print detailed heap and state dumps upon process crash. |
AVM_VERBOSE_ABORT | AVM_VERBOSE_ABORT | Provides detailed error messages when the VM performs a hard abort. |
AVM_PEDANTIC_WARNINGS | -pedantic | Enables strict compiler warnings to catch potential bugs during build. |
Sources: src/libAtomVM/CMakeLists.txt:135-143, src/libAtomVM/CMakeLists.txt:178-191
Debug Symbol Support
For Generic UNIX and embedded targets, AtomVM supports standard GDB-compatible debug symbols. The build system automatically applies -ggdb or -g flags based on the compiler identified (GCC or Clang), ensuring that external debuggers can map machine instructions back to C source code.
Sources: src/libAtomVM/CMakeLists.txt:130-134
Execution Flow and Monitoring
The debugging workflow varies significantly depending on the target platform, moving from high-level console logging to low-level hardware tracing.
Hardware and Serial Debugging
On microcontrollers (ESP32, STM32, RP2), debugging relies heavily on Serial-over-USB interfaces.
- Serial Consoles: Tools like
minicomorscreenare used to capturestdoutandstderremitted by the VM. On STM32 platforms, the console defaults toUSART2(8N1, 115200 baud). - JTAG/SWD: For STM32, hardware debugging is supported via
st-linkdevices, enabling JTAG debugging and flash management through thest-flashutility. - Post-Mortem Analysis: When
AVM_PRINT_PROCESS_CRASH_DUMPSis enabled, the serial console receives a dump of the process mailbox, stack, and heap, which is essential for diagnosing memory corruption or logic errors in actor-based code.
Sources: doc/src/getting-started-guide.md:70-73, doc/src/getting-started-guide.md:330-335, doc/src/getting-started-guide.md:368-372
Debugging Workflow Diagram
The following diagram illustrates the flow from code implementation to diagnostic feedback across different platforms:
This diagram shows the various paths a developer can take to retrieve diagnostic information depending on the deployment target.
Sources: doc/src/getting-started-guide.md:15-25, examples/emscripten/run_script.html:45-55
Tracing and Stack Management
Tracing in AtomVM is integrated into the core scheduler and memory management units.
Stacktrace Generation
The module stacktrace.c (managed via AVM_CREATE_STACKTRACES) is responsible for capturing the call hierarchy when an exception occurs. Because AtomVM is designed for tiny micro-controllers (some with as little as 128KB RAM), stacktraces are often stored efficiently or limited in depth to prevent heap exhaustion.
Sources: src/libAtomVM/CMakeLists.txt:189, doc/src/welcome-to-atomvm.md:123-125
Advanced Tracing Logic
When ENABLE_ADVANCED_TRACE is active, the VM provides a step-by-step account of opcode execution. This is particularly useful for debugging the JIT (Just-In-Time) compiler or the BEAM emulator itself.
The sequence diagram represents the conditional check performed during the instruction fetch cycle when advanced tracing is enabled.
Sources: src/libAtomVM/CMakeLists.txt:140-142, src/libAtomVM/debug.c
Web and Script Debugging
In the Emscripten (WebAssembly) port, AtomVM bridges Erlang/Elixir execution with the JavaScript environment. Debugging in this context involves:
- Synchronous/Asynchronous scripts: Using
emscripten:run_script/1,2to trigger JavaScriptalert()orconsole.log()calls from the BEAM. - Worker Thread Monitoring: Tracing execution across main threads and worker threads (used in SMP builds).
- DOM Inspection: Manipulating the DOM to display performance metrics or counter values for visual debugging.
Sources: examples/emscripten/run_script.html:45-58
Summary of Debugging significance
Debugging and tracing in AtomVM provide the necessary transparency for developing robust IoT applications. By providing a combination of compile-time flags for VM internals and standard serial/JTAG interfaces for hardware, AtomVM ensures that even the most constrained 80s-era hardware specifications can be effectively debugged using modern functional programming practices.
Sources: doc/src/welcome-to-atomvm.md:52-58, doc/src/getting-started-guide.md:510-515