[Lldb-commits] [lldb] [lldb] Skip local variable declarations at start of Wasm function (PR #190093)

Maarten Steevens via lldb-commits lldb-commits at lists.llvm.org
Thu Apr 2 01:39:05 PDT 2026


MaartenS11 wrote:

For just disassembly it appears to work (although the addresses are shifted):
```
llvm-project/build/bin/lldb test-dbg.wasm
(lldb) target create "test-dbg.wasm"
Current executable set to '/Users/maarten/Projects/tinygo-warduino-test/tmp/test-dbg.wasm' (wasm32).
(lldb) disassemble -n _main
test-dbg.wasm`_main:
test-dbg.wasm[0x81] <+3>:   global.get 0
test-dbg.wasm[0x87] <+9>:   i32.const 16
test-dbg.wasm[0x89] <+11>:  i32.sub
test-dbg.wasm[0x8a] <+12>:  local.set 0
test-dbg.wasm[0x8c] <+14>:  local.get 0
test-dbg.wasm[0x8e] <+16>:  global.set 0
test-dbg.wasm[0x94] <+22>:  local.get 0
test-dbg.wasm[0x96] <+24>:  i32.const 0
test-dbg.wasm[0x98] <+26>:  i32.store 12
test-dbg.wasm[0x9b] <+29>:  block
test-dbg.wasm[0x9d] <+31>:  loop                             ; label2:
test-dbg.wasm[0x9f] <+33>:  local.get 0
test-dbg.wasm[0xa1] <+35>:  i32.load 12
test-dbg.wasm[0xa4] <+38>:  i32.const 50
test-dbg.wasm[0xa6] <+40>:  i32.lt_s
test-dbg.wasm[0xa7] <+41>:  i32.const 1
test-dbg.wasm[0xa9] <+43>:  i32.and
test-dbg.wasm[0xaa] <+44>:  i32.eqz
test-dbg.wasm[0xab] <+45>:  br_if  1                         ; 1: up to label2
test-dbg.wasm[0xad] <+47>:  local.get 0
test-dbg.wasm[0xaf] <+49>:  i32.load 12
test-dbg.wasm[0xb2] <+52>:  call   0
test-dbg.wasm[0xb8] <+58>:  local.get 0
test-dbg.wasm[0xba] <+60>:  i32.load 12
test-dbg.wasm[0xbd] <+63>:  call   1
test-dbg.wasm[0xc3] <+69>:  call   0
test-dbg.wasm[0xc9] <+75>:  local.get 0
test-dbg.wasm[0xcb] <+77>:  local.get 0
test-dbg.wasm[0xcd] <+79>:  i32.load 12
test-dbg.wasm[0xd0] <+82>:  i32.const 1
test-dbg.wasm[0xd2] <+84>:  i32.add
test-dbg.wasm[0xd3] <+85>:  i32.store 12
test-dbg.wasm[0xd6] <+88>:  br     0                         ; 0: up to label3
test-dbg.wasm[0xd8] <+90>:  end
test-dbg.wasm[0xd9] <+91>:  end
test-dbg.wasm[0xda] <+92>:  local.get 0
test-dbg.wasm[0xdc] <+94>:  i32.const 16
test-dbg.wasm[0xde] <+96>:  i32.add
test-dbg.wasm[0xdf] <+97>:  global.set 0
test-dbg.wasm[0xe5] <+103>: return
test-dbg.wasm[0xe6] <+104>: end
(lldb)
```
Which matches with the instructions seen in objdump:
```
0000e3 func[2] <_main>:
 0000e4: 01 7f                      | local[0] type=i32
 0000e6: 23 80 80 80 80 00          | global.get 0 <__stack_pointer>
 0000ec: 41 10                      | i32.const 16
 0000ee: 6b                         | i32.sub
 0000ef: 21 00                      | local.set 0
 0000f1: 20 00                      | local.get 0
 0000f3: 24 80 80 80 80 00          | global.set 0 <__stack_pointer>
 0000f9: 20 00                      | local.get 0
 0000fb: 41 00                      | i32.const 0
 0000fd: 36 02 0c                   | i32.store 2 12
 000100: 02 40                      | block
 000102: 03 40                      |   loop
 000104: 20 00                      |     local.get 0
 000106: 28 02 0c                   |     i32.load 2 12
 000109: 41 32                      |     i32.const 50
 00010b: 48                         |     i32.lt_s
 00010c: 41 01                      |     i32.const 1
 00010e: 71                         |     i32.and
 00010f: 45                         |     i32.eqz
 000110: 0d 01                      |     br_if 1
 000112: 20 00                      |     local.get 0
 000114: 28 02 0c                   |     i32.load 2 12
 000117: 10 80 80 80 80 00          |     call 0 <print_int>
 00011d: 20 00                      |     local.get 0
 00011f: 28 02 0c                   |     i32.load 2 12
 000122: 10 81 80 80 80 00          |     call 1 <fib>
 000128: 10 80 80 80 80 00          |     call 0 <print_int>
 00012e: 20 00                      |     local.get 0
 000130: 20 00                      |     local.get 0
 000132: 28 02 0c                   |     i32.load 2 12
 000135: 41 01                      |     i32.const 1
 000137: 6a                         |     i32.add
 000138: 36 02 0c                   |     i32.store 2 12
 00013b: 0c 00                      |     br 0
 00013d: 0b                         |   end
 00013e: 0b                         | end
 00013f: 20 00                      | local.get 0
 000141: 41 10                      | i32.const 16
 000143: 6a                         | i32.add
 000144: 24 80 80 80 80 00          | global.set 0 <__stack_pointer>
 00014a: 0f                         | return
 00014b: 0b                         | end
```
On the other hand the moment I start debugging, the instructions suddenly look a bit strange:
```
(lldb) disassemble -n _main
test-dbg.wasm`_main:
->  0xe6 <+3>: end
    0xe7 <+4>: loop   unknown_type              ; label0:
    0xe9 <+6>: return
    0xea <+7>: end
```
It seems that the addresses are now shifted regardless of when I'm debugging or not. At `0xe6` there is an `end` according to lldb (see above). But according to objdump it's supposed to be the first instruction of the function `global.get 0`.

Looking at `disassemble -s 0x81 -c 20`, with `0x81` being the address I got from the first disassembly when not debugging I get the expected instructions. So the shift to skip the locals appears to work but the adresses are all shifted by a certain amount.
```
(lldb) disassemble -s 0x81 -c 20
test-dbg.wasm`fib:
    0x81 <+26>: global.get 0
    0x87 <+32>: i32.const 16
    0x89 <+34>: i32.sub
    0x8a <+35>: local.set 0
    0x8c <+37>: local.get 0
    0x8e <+39>: global.set 0
    0x94 <+45>: local.get 0
    0x96 <+47>: i32.const 0
    0x98 <+49>: i32.store 12
    0x9b <+52>: block
    0x9d <+54>: loop                             ; label2:
    0x9f <+56>: local.get 0
    0xa1 <+58>: i32.load 12
    0xa4 <+61>: i32.const 50
    0xa6 <+63>: i32.lt_s
    0xa7 <+64>: i32.const 1
    0xa9 <+66>: i32.and
    0xaa <+67>: i32.eqz
    0xab <+68>: br_if  1                         ; 1: up to label2
    0xad <+70>: local.get 0
```

https://github.com/llvm/llvm-project/pull/190093


More information about the lldb-commits mailing list