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
Merge pull request #2264 from pguyot/w15/add-opcodes
Improve DWARF debugging support
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
@@ -61,6 +63,7 @@ When enabled, each precompiled module includes an ELF object with DWARF debug se
61
63
* Label symbols
62
64
* Source file and line number mappings
63
65
* Context structure type information for inspecting VM registers
66
+
* Named variable locations (when compiled with `beam_debug_info`, OTP 28+)
64
67
65
68
## DWARF debug support
66
69
@@ -97,7 +100,58 @@ The DWARF debug information includes location tracking for Erlang x registers. U
97
100
98
101
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`).
99
102
100
-
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
+
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.
104
+
105
+
#### Named variable inspection
106
+
107
+
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.
108
+
109
+
To enable this, add `beam_debug_info` as a compile attribute in your module:
110
+
111
+
```erlang
112
+
-compile([beam_debug_info]).
113
+
```
114
+
115
+
Or pass it as a compiler flag:
116
+
117
+
```shell
118
+
$ erlc +beam_debug_info my_module.erl
119
+
```
120
+
121
+
```{warning}
122
+
The `beam_debug_info` option disables several compiler optimizations (constant folding,
123
+
binary match optimization, etc.) to preserve variable-to-register mappings. Use it only
124
+
for modules you intend to debug, not for production builds.
125
+
```
126
+
127
+
With `beam_debug_info` enabled, the debugger shows named variables:
128
+
129
+
```
130
+
$ lldb -- ./AtomVM my_module.avm
131
+
(lldb) settings set plugin.jit-loader.gdb.enable on
132
+
(lldb) breakpoint set -f my_module.erl -l 10
133
+
(lldb) run
134
+
```
135
+
136
+
```
137
+
Process stopped
138
+
* thread #1, stop reason = breakpoint 1.1
139
+
frame #0: JIT`my_module:my_fun/1(ctx=0x...) at my_module.erl:10
140
+
(lldb) frame variable N M
141
+
(unsigned long) N = 687
142
+
(unsigned long) M = 703
143
+
```
144
+
145
+
The variables are displayed as raw tagged terms, just like x registers. Use `term_to_int()` to convert small integers:
146
+
147
+
```
148
+
(lldb) print term_to_int(N)
149
+
(avm_int_t) 42
150
+
(lldb) print term_to_int(M)
151
+
(avm_int_t) 43
152
+
```
153
+
154
+
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.
101
155
102
156
#### Backtraces
103
157
@@ -111,12 +165,15 @@ When the JIT compiler has cached an x register in a native CPU register, the deb
111
165
112
166
#### Source line mapping
113
167
114
-
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.
168
+
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:
169
+
170
+
```
171
+
(lldb) breakpoint set -f my_module.erl -l 15
172
+
```
115
173
116
174
```{note}
117
-
LLDB 19 (including Apple's system LLDB shipped with Xcode) has a regression in the JIT loader
118
-
that causes hangs when resolving breakpoints in JIT-loaded modules. Use LLDB 20 or later.
119
-
On macOS, install it from [MacPorts](https://www.macports.org/) (`port install lldb-20`) or
175
+
LLDB 19 has a regression in the JIT loader that causes hangs when resolving breakpoints in JIT-loaded modules. Use LLDB 20 or later.
176
+
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
120
177
build from the [LLVM project source](https://github.com/llvm/llvm-project).
0 commit comments