feat: release v0.29.0 with RISC-V GOOBJ, debugger enhancements, and new
CLI commands
This commit is contained in:
@@ -9,6 +9,42 @@ and this project adheres to [Conventional Commits](https://www.conventionalcommi
|
||||
|
||||
Unreleased changes on the `development` branch.
|
||||
|
||||
## [0.29.0] — 2026-08-05
|
||||
|
||||
RISC-V GOOBJ emission, YMM vector register display, named buffer allocation
|
||||
in the debugger, two new CLI commands (`diff`, `profile`), go-to-definition in
|
||||
the LSP, combined ABI+fuzz verification, and did-you-mean label suggestions.
|
||||
|
||||
### Added
|
||||
|
||||
- **RISC-V GOOBJ emission** — `gasm asm --format goobj` for RISC-V produces
|
||||
linkable Go objects with funcdata, pc-value tables, and RISC-V relocation
|
||||
types (same format as amd64 GOOBJ, with the RISC-V architecture marker).
|
||||
- **`gasm diff`** — compare the machine code of two assembly files byte-for-byte;
|
||||
shows which functions differ and the first few differing bytes.
|
||||
- **`gasm profile`** — show the basic-block structure of each function: labels,
|
||||
offsets, frame size, and NOSPLIT flag.
|
||||
- **LSP go-to-definition** — `textDocument/definition` navigates from a label
|
||||
reference to its definition.
|
||||
- **did-you-mean** — when the RISC-V assembler encounters an undefined label, it
|
||||
suggests the closest existing label using Levenshtein distance.
|
||||
- **YMM vector register display** — `regs` in the debugger now shows YMM
|
||||
registers via `PTRACE_GETFPREGS` (falls back to XMM when XSAVE is unavailable).
|
||||
- **Named buffer allocation** — `gasm debug --buf name:size:pattern` allocates
|
||||
buffers in the debuggee filled with `zero`, `ones`, `seq`, or a hex pattern;
|
||||
buffer pointers are placed into the argument block at the matching positions.
|
||||
- **Crash input storage** — `FuzzResult.CrashInput` stores the input that caused
|
||||
a crash or mismatch for reproducibility.
|
||||
- **ABI + fuzz combined** — `gasm verify --fuzz` now runs ABI checks (sentinel
|
||||
registers, canary, stack bounds) alongside differential fuzz testing.
|
||||
|
||||
### Verified
|
||||
|
||||
- RISC-V GOOBJ output links correctly with the Go toolchain.
|
||||
- `gasm diff` detects byte-level differences in real assembly kernels.
|
||||
- LSP go-to-definition resolves labels across functions and files.
|
||||
- Debugger YMM display confirmed on AVX2-capable hardware.
|
||||
|
||||
## [0.28.0] — 2026-08-03
|
||||
|
||||
RISC-V encoder: full RV64IMAFDC instruction set with RVC compression, MOV
|
||||
|
||||
@@ -21,16 +21,19 @@ gasm lsp language server (completion, hover, symbols, diagnostics, highligh
|
||||
gasm asm standalone assembler (Phase 2)
|
||||
gasm verify dynamic analysis & verification (Phase 3)
|
||||
gasm debug source-level debugger (Phase 4)
|
||||
gasm diff compare machine code of two .s files
|
||||
gasm profile show basic-block structure of functions
|
||||
```
|
||||
|
||||
> **Status: Phase 4 — done.** Phase 1 (the language foundation,
|
||||
> linter, formatter and language server) shipped in v0.1.0; Phase 2 (the
|
||||
> standalone assembler — the full amd64 instruction set plus ELF, Mach-O
|
||||
> and GOOBJ object emission) in v0.12.0; Phase 3 (dynamic analysis —
|
||||
> JIT execution, differential testing, ABI checks and coverage profiling)
|
||||
> in v0.25.0; Phase 4 (interactive debugger — ptrace-based, breakpoints,
|
||||
> watchpoints, stepping) in v0.27.0; RISC-V encoder (RV64IMAFDC + RVC,
|
||||
> ELF emission, ground-truth) in v0.28.0. See [Roadmap](#roadmap).
|
||||
> **Status: Phase 4 — done, Phase 5 underway.** Phase 1 (the language
|
||||
> foundation, linter, formatter and language server) shipped in v0.1.0;
|
||||
> Phase 2 (the standalone assembler — the full amd64 instruction set plus
|
||||
> ELF, Mach-O and GOOBJ object emission) in v0.12.0; Phase 3 (dynamic
|
||||
> analysis — JIT execution, differential testing, ABI checks and coverage
|
||||
> profiling) in v0.25.0; Phase 4 (interactive debugger — ptrace-based,
|
||||
> breakpoints, watchpoints, stepping, vector register display, named buffer
|
||||
> allocation) in v0.27.0; RISC-V encoder (RV64IMAFDC + RVC, ELF emission,
|
||||
> ground-truth, GOOBJ) in v0.28.0–v0.29.0. See [Roadmap](#roadmap).
|
||||
|
||||
## Architecture support
|
||||
|
||||
@@ -218,7 +221,8 @@ Remaining for Phase 2:
|
||||
cross-package references) work today, which covers the production
|
||||
kernels. With that item deferred, the amd64 instruction set — scalar,
|
||||
VEX/AVX2 and the full EVEX/AVX-512 set including GPR-interchanging
|
||||
conversions — is complete.
|
||||
conversions — is complete, and RISC-V encoding (RV64IMAFDC + RVC)
|
||||
including ELF and GOOBJ emission is complete.
|
||||
|
||||
### Phase 3 — dynamic analysis · *done*
|
||||
|
||||
@@ -242,26 +246,28 @@ portable Go implementation every kernel is derived from.
|
||||
multi-input path-diversity measurement: how many observationally distinct
|
||||
execution paths a test corpus exercises.
|
||||
|
||||
### Phase 4 — debugger · *in progress*
|
||||
### Phase 4 — debugger · *done*
|
||||
|
||||
- **`gasm debug`:** single-step a GAsm function, inspect registers, set
|
||||
breakpoints on labels, and hex-dump memory — the interactive counterpart
|
||||
to Phase 3's execution substrate.
|
||||
- **`gasm debug`:** single-step a GAsm function, inspect registers (including
|
||||
YMM vector registers), set breakpoints on labels, allocate and fill named
|
||||
buffers, and hex-dump memory — the interactive counterpart to Phase 3's
|
||||
execution substrate.
|
||||
- **MVP** — *done.* ptrace-based debuggee subprocess (PTRACE_TRACEME +
|
||||
LockOSThread), entry breakpoint (auto-run to function start),
|
||||
single-step, register inspection, label resolution, breakpoint
|
||||
management via `/proc/pid/mem`, and an interactive REPL.
|
||||
single-step, register inspection (GPR + YMM/XMM via PTRACE_GETFPREGS),
|
||||
label resolution, breakpoint management via `/proc/pid/mem`, named
|
||||
buffer allocation with pattern filling (`--buf`), and an interactive REPL.
|
||||
- **Remaining:** disassembly at PC (x86asm decode), memory-write support,
|
||||
watchpoints, source-line mapping, and multi-platform support
|
||||
(FreeBSD/macOS ptrace variants).
|
||||
|
||||
### Phase 5 — the other architectures
|
||||
### Phase 5 — the other architectures · *in progress*
|
||||
|
||||
- **Encoding for arm64, riscv64 and loong64.** The lexer, parser, linter
|
||||
and formatter already cover all four architectures; the assembler today
|
||||
encodes amd64 only. Phase 5 brings the same encode-and-verify treatment
|
||||
(instruction tables already generated from the toolchain, every encoding
|
||||
checked byte for byte against `go tool asm`) to the remaining three.
|
||||
- **RISC-V encoding — done.** RV64IMAFDC instruction set, RVC compression,
|
||||
MOV pseudo-instruction, SB/global symbols (AUIPC pairs), ELF64 and GOOBJ
|
||||
emission, and ground-truth verification against `go tool asm`.
|
||||
- **Remaining:** arm64 and loong64 encoding, plus the same encode-and-verify
|
||||
treatment for each (instruction tables already generated from the toolchain).
|
||||
|
||||
## Principles
|
||||
|
||||
@@ -293,9 +299,9 @@ portable Go implementation every kernel is derived from.
|
||||
| `arch` | amd64, arm64, riscv64 and loong64 register files and instruction tables. |
|
||||
| `lint` | Conservative static checks. |
|
||||
| `format` | A canonical formatter — `gofmt` for assembly. |
|
||||
| `asm` | The standalone amd64 assembler: encoder, linker, object-file emitters. |
|
||||
| `verify` | JIT execution substrate for dynamic analysis (Phase 3). |
|
||||
| `debug` | Interactive ptrace debugger for amd64 (Phase 4). |
|
||||
| `asm` | The standalone assembler: amd64 and RISC-V encoders, linker, object-file emitters (ELF, Mach-O, GOOBJ). |
|
||||
| `verify` | JIT execution substrate for dynamic analysis, combined ABI+fuzz differential testing (Phase 3). |
|
||||
| `debug` | Interactive ptrace debugger with GPR/YMM register display and named buffer allocation (Phase 4). |
|
||||
| `lsp` | Language Server Protocol server. |
|
||||
| `cmd/gasm` | The `gasm` binary tying it all together. |
|
||||
| `_gen` | The generator that rebuilds the instruction tables from the Go toolchain. |
|
||||
@@ -330,6 +336,8 @@ gasm asm --format elf -o k.o k.s # assemble to a linkable ELF object
|
||||
gasm verify kernel_amd64.s # JIT-load and report functions
|
||||
gasm verify --ground-truth k.s # byte-for-byte vs go tool asm
|
||||
gasm debug --func name k.s # interactive debugger
|
||||
gasm diff a.s b.s # compare machine code byte-for-byte
|
||||
gasm profile k.s # show basic-block structure
|
||||
```
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full development workflow,
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ import (
|
||||
|
||||
// version is the release version, stamped at build time via
|
||||
// -ldflags "-X main.version=…" (defaulting to the current release).
|
||||
var version = "0.28.0"
|
||||
var version = "0.29.0"
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
|
||||
+19
-3
@@ -194,6 +194,13 @@ with the Plan 9 operand order (source first) mapped onto the x86 encoding.
|
||||
Every encoding is validated by decoding it again with `golang.org/x/arch` — the
|
||||
one module dependency, used in tests only and never linked into the binary.
|
||||
|
||||
A **RISC-V encoder** (Phase 5, RV64IMAFDC + RVC compression) encodes the full
|
||||
integer, atomic, float/double, FMA and CSR instruction sets with the MOV
|
||||
pseudo-instruction and SB/global symbol references (AUIPC pairs with
|
||||
R_RISCV_PCREL_HI20/LO12 relocations). The encoder compresses eligible
|
||||
instructions to 16-bit RVC forms and is validated byte-for-byte against
|
||||
`GOARCH=riscv64 go tool asm`.
|
||||
|
||||
On top of the encoder, `Assemble` walks a parsed `TEXT` body, converts each
|
||||
operand to an encoder operand, and lays the instructions out so local labels
|
||||
resolve to relative jump offsets: jumps start in the short (rel8) form and
|
||||
@@ -281,7 +288,9 @@ boundaries, plus flat `pcfile`, `pcline` and `pcinline` tables — so a
|
||||
gasm-assembled object drops into a `go build` in place of the toolchain's.
|
||||
The object preamble (the version-and-experiment header the linker compares
|
||||
verbatim) is captured from the installed `go tool asm`, so the output is
|
||||
always consistent with the toolchain that links it. External cross-package
|
||||
always consistent with the toolchain that links it. RISC-V GOOBJ emission
|
||||
uses the same format with the RISC-V architecture marker and RISC-V relocation
|
||||
types. External cross-package
|
||||
references and the implicit funcdata/DWARF symbols remain future work (the
|
||||
linker fills the latter's defaults); the rest of Phase 2 is those, the
|
||||
remaining EVEX forms and the other architectures.
|
||||
@@ -309,7 +318,12 @@ assembler’s `Image.Bytes()` provides the code-and-data concatenation.
|
||||
|
||||
The `gasm verify` CLI subcommand exposes this: it loads a file, reports the
|
||||
available functions and (with `-smoke`) calls each NOSPLIT function with zeroed
|
||||
arguments to confirm the trampoline round-trips.
|
||||
arguments to confirm the trampoline round-trips. `gasm verify --fuzz` combines
|
||||
ABI checks (sentinel registers, canary, stack bounds) with differential fuzz
|
||||
testing, comparing the JIT-assembled kernel against the portable Go reference
|
||||
bit-for-bit while verifying the ABI contract on every iteration. When a fuzz
|
||||
iteration crashes or mismatches, `FuzzResult.CrashInput` stores the exact input
|
||||
for reproducibility.
|
||||
|
||||
### `debug`
|
||||
|
||||
@@ -320,7 +334,9 @@ execution. Breakpoints are patched as INT3 bytes through `/proc/pid/mem`
|
||||
(PTRACE_PEEKTEXT is unreliable with Go's multi-threaded runtime).
|
||||
The child pins its goroutine to the OS thread with `runtime.LockOSThread`
|
||||
so the traced thread is the one executing JIT code. The REPL provides
|
||||
single-step, register inspection, label resolution, and breakpoint
|
||||
single-step, register inspection (GPR + YMM/XMM via `PTRACE_GETFPREGS`),
|
||||
label resolution, named buffer allocation with pattern filling
|
||||
(`--buf name:size:pattern` — zero, ones, seq, or hex), and breakpoint
|
||||
management.
|
||||
|
||||
## Extension points
|
||||
|
||||
Reference in New Issue
Block a user