Skip to content

Conversation

MaxDesiatov
Copy link
Member

@MaxDesiatov MaxDesiatov commented Oct 7, 2025

Per a discussion, following options are available for enabling breakpoints in WasmKit:

One of the main difficulties in implementing breakpoint in WasmKit is that our internal instruction set is not a 1:1 map of Wasm instruction set, unlike IPInt in JSC. Therefore, we need a way to translate address between Wasm byte offset <-> internal ISeq.

Option 1: Record address translation table during compiling wasm bytecode to internal ISeq when a first breakpoint is set to the function, then patch the internal ISeq to set breakpoint using the table.
We only need one-time re-compilation to record the table, so later breakpoint settings will be trivial, but it adds non-trivial memory footprint to hold the table.

Option 2: Patch the original wasm bytecode to replace the target instruction with a special reserved breakpoint instruction and compile to the internal ISeq.
We don't need to hold the addr translation table but need to re-compile every time a new breakpoint is set.

Option 3: Implement in-place interpreter along side with the current fast interpreter.
This is the simplest approach and what wamr and JSC are doing for their classic interpreter and IPInt respectively, but need to maintain two interpreters.

We've decided to proceed with Option 2, where a special breakpoint instruction is added to the VM, which is translated from 0xFF Wasm binary code. This code can never be supplied by the user, as it isn't enabled in the parser. In a future PR we'll provide public methods on module instances like func enableBreakpoint that flips this instruction in in-memory module source and recompiles the corresponding function to VM bytecode with the new breakpoint instruction.

@MaxDesiatov MaxDesiatov changed the title Use package access control for BinaryInstructionDecoder Add breakpoint VM instruction Oct 7, 2025
@JDevlieghere
Copy link

JDevlieghere commented Oct 7, 2025

FWIW, LLDB and other runtimes (like WARM) expect/use unreachable (0x00, unconditional trap) for breakpoints. What's the motivation for using 0xFF instead?

Corresponding code in LLDB: https://github.com/llvm/llvm-project/blob/c16d25282e7169cb8a19d9fa385cf7220dd65ac5/lldb/source/Target/Platform.cpp#L2079

@MaxDesiatov
Copy link
Member Author

MaxDesiatov commented Oct 7, 2025

FWIW, LLDB and other runtimes (like WARM) expect/use unreachable (0x00, unconditional trap) for breakpoints. What's the motivation for using 0xFF instead?

That's a fair point, I initially didn't know LLDB and WAMR settled on 0x00 and thought that we'd like this to be distinct from the the usual trap instruction that's executed after all in Swift's fatalError, force unwrapping, and such. But makes sense you'd want those to trigger a breakpoint stop as well. Considering that, I'm on board with translating unreachable 0x00 in Wasm binaries into VM breakpoints if that's fine by @kateinoigakukun.

@MaxDesiatov
Copy link
Member Author

MaxDesiatov commented Oct 7, 2025

Thinking about it more, this PR would have to be significantly modified to use 0x00 (unreachable) instead of 0xFF (currently unrecognized instruction). We'll never have opcode evaluate to 0x00 in visitUnknown, so we'd have to update existing visitUnreachable in Translator.swift, which currently looks like this:

    mutating func visitUnreachable() throws -> Output {
        emit(.unreachable)
        try markUnreachable()
    }

MaxDesiatov and others added 8 commits October 8, 2025 09:54
This is a preparation for a future internal breakpoint instruction, for which we need `visitUnknown` of `BinaryInstructionDecoder` to be available in the `WasmKit` module.

Bumped `swift-tools-version` to 6.0 to get proper support for `package` in SwiftPM enabled.
@MaxDesiatov MaxDesiatov merged commit ccbdb53 into main Oct 8, 2025
14 of 15 checks passed
@MaxDesiatov MaxDesiatov deleted the package-bid branch October 8, 2025 09:12
@MaxDesiatov MaxDesiatov moved this to Done in WasmKit Oct 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants