You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement nif_start (179), executable_line (183) and debug_line (184)
- `nif_start` is implemented as no-op, preventing crash
- `executable_line` is implemented on jit+dwarf for additional line
information for debuggers
- `debug_line` is implemented on jit+dwarf for additional line
information and variable mapping for debuggers
Also fix DWARF generation by emitting DW_LNS_set_prologue_end which lldb
needs to resolve breakpoints at function lines with `executable_line`.
Also clean up `jit_dwarf.erl`
Signed-off-by: Paul Guyot <pguyot@kallisys.net>
@@ -60,6 +62,7 @@ When enabled, each precompiled module includes an ELF object with DWARF debug se
60
62
* Label symbols
61
63
* Source file and line number mappings
62
64
* Context structure type information for inspecting VM registers
65
+
* Named variable locations (when compiled with `beam_debug_info`, OTP 28+)
63
66
64
67
## DWARF debug support
65
68
@@ -96,7 +99,58 @@ The DWARF debug information includes location tracking for Erlang x registers. U
96
99
97
100
The x register values are displayed as raw tagged terms. For small integers, the value is `(term >> 4)`, so `x[0] = 143` means the integer `8` (since `143 = 8 << 4 | 0xf`).
98
101
99
-
When the JIT compiler has cached an x register in a native CPU register, the debugger reads it directly from the CPU register instead of memory — this is tracked automatically through DWARF location lists.
102
+
When the JIT compiler has cached an x register in a native CPU register, the debugger reads it directly from the CPU register instead of memory, this is tracked automatically through DWARF location lists.
103
+
104
+
#### Named variable inspection
105
+
106
+
When an Erlang module is compiled with the `beam_debug_info` option (OTP 28+), the compiler emits `debug_line` opcodes that carry variable-to-register mappings. The JIT DWARF backend uses these to generate named variable entries, so the debugger can display Erlang variable names instead of raw register indices.
107
+
108
+
To enable this, add `beam_debug_info` as a compile attribute in your module:
109
+
110
+
```erlang
111
+
-compile([beam_debug_info]).
112
+
```
113
+
114
+
Or pass it as a compiler flag:
115
+
116
+
```shell
117
+
$ erlc +beam_debug_info my_module.erl
118
+
```
119
+
120
+
```{warning}
121
+
The `beam_debug_info` option disables several compiler optimizations (constant folding,
122
+
binary match optimization, etc.) to preserve variable-to-register mappings. Use it only
123
+
for modules you intend to debug, not for production builds.
124
+
```
125
+
126
+
With `beam_debug_info` enabled, the debugger shows named variables:
127
+
128
+
```
129
+
$ lldb -- ./AtomVM my_module.avm
130
+
(lldb) settings set plugin.jit-loader.gdb.enable on
131
+
(lldb) breakpoint set -f my_module.erl -l 10
132
+
(lldb) run
133
+
```
134
+
135
+
```
136
+
Process stopped
137
+
* thread #1, stop reason = breakpoint 1.1
138
+
frame #0: JIT`my_module:my_fun/1(ctx=0x...) at my_module.erl:10
139
+
(lldb) frame variable N M
140
+
(unsigned long) N = 687
141
+
(unsigned long) M = 703
142
+
```
143
+
144
+
The variables are displayed as raw tagged terms, just like x registers. Use `term_to_int()` to convert small integers:
145
+
146
+
```
147
+
(lldb) print term_to_int(N)
148
+
(avm_int_t) 42
149
+
(lldb) print term_to_int(M)
150
+
(avm_int_t) 43
151
+
```
152
+
153
+
The variable locations are tracked through DWARF location lists, so the debugger shows the correct value at each point in the function. A variable that moves from one register to another (or goes out of scope) is handled automatically.
100
154
101
155
#### Backtraces
102
156
@@ -110,12 +164,15 @@ When the JIT compiler has cached an x register in a native CPU register, the deb
110
164
111
165
#### Source line mapping
112
166
113
-
If the Erlang source was compiled with debug information and the BEAM Line chunk is present, the debugger maps JIT code addresses to source file and line numbers.
167
+
If the Erlang source was compiled with debug information and the BEAM Line chunk is present, the debugger maps JIT code addresses to source file and line numbers. You can set breakpoints by file and line:
168
+
169
+
```
170
+
(lldb) breakpoint set -f my_module.erl -l 15
171
+
```
114
172
115
173
```{note}
116
-
LLDB 19 (including Apple's system LLDB shipped with Xcode) has a regression in the JIT loader
117
-
that causes hangs when resolving breakpoints in JIT-loaded modules. Use LLDB 20 or later.
118
-
On macOS, install it from [MacPorts](https://www.macports.org/) (`port install lldb-20`) or
174
+
LLDB 19 has a regression in the JIT loader that causes hangs when resolving breakpoints in JIT-loaded modules. Use LLDB 20 or later.
175
+
On macOS, you can use lldb that ships with Xcode 26+ or install lldb 20 from [MacPorts](https://www.macports.org/) (`port install lldb-20`) or
119
176
build from the [LLVM project source](https://github.com/llvm/llvm-project).
0 commit comments