chore: prepare release v0.33.0
Release / build (amd64, linux) (push) Successful in 49s
Release / build (arm64, linux) (push) Successful in 43s
Release / build (loong64, linux) (push) Successful in 46s
Release / build (riscv64, linux) (push) Successful in 45s
Test / vet (push) Successful in 47s
Release / release (push) Successful in 18s
Test / test (push) Successful in 2m39s
Test / build (push) Successful in 43s
Release / build (amd64, linux) (push) Successful in 49s
Release / build (arm64, linux) (push) Successful in 43s
Release / build (loong64, linux) (push) Successful in 46s
Release / build (riscv64, linux) (push) Successful in 45s
Test / vet (push) Successful in 47s
Release / release (push) Successful in 18s
Test / test (push) Successful in 2m39s
Test / build (push) Successful in 43s
This commit is contained in:
@@ -11,6 +11,62 @@ and this project adheres to [Conventional Commits](https://www.conventionalcommi
|
|||||||
|
|
||||||
-
|
-
|
||||||
|
|
||||||
|
## [0.33.0] — 2026-09-14
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Stack-split guards in `gasm asm`.** Every framed function now gets
|
||||||
|
the morestack prologue check and the trailing morestack block
|
||||||
|
(`CALL runtime.morestack_noctxt`), byte-identical to the toolchain's
|
||||||
|
`stacksplit` output on all four architectures: the small, medium and
|
||||||
|
big frame classes, auto-NOSPLIT leaves, the materialised constants of
|
||||||
|
large frames (arm64 `R27`, riscv64 `X31`, loong64 `R30`) and the
|
||||||
|
arm64 extrasize rule. Assembled objects are therefore linkable for
|
||||||
|
split functions, not only `NOSPLIT` leaves.
|
||||||
|
- **`gasm dis`.** Standalone disassembly through `golang.org/x/arch`:
|
||||||
|
a `.s` file is assembled and listed per `TEXT` function with local
|
||||||
|
labels at their real offsets, or raw bytes from a file or stdin are
|
||||||
|
disassembled linearly (`-a` selects the architecture). The debugger
|
||||||
|
shares the same decoder instead of carrying its own.
|
||||||
|
- **`gasm fmt -l` and `-d`.** Check mode lists files whose formatting
|
||||||
|
differs; diff mode prints a unified diff from the project's own
|
||||||
|
LCS-based differ, with GNU header semantics.
|
||||||
|
- **LSP cross-file navigation.** Go-to-definition and find references
|
||||||
|
fall back from local labels to the `TEXT` functions of every open
|
||||||
|
document, and rename follows the same cross-file matching.
|
||||||
|
- **Large frame offsets on riscv64 and arm64.** Frame-relative loads
|
||||||
|
and stores beyond the signed 12-bit immediate range materialise the
|
||||||
|
address through the toolchain temp register (riscv64 `X31`, arm64
|
||||||
|
`R27`) instead of silently truncating the offset (riscv64) or
|
||||||
|
rejecting the instruction (arm64); arm64 frame sizes now add the
|
||||||
|
toolchain's extrasize exactly (+8 when the frame leaves an alignment
|
||||||
|
gap, +16 when it is already aligned).
|
||||||
|
- **Tail calls `JMP sym(SB)`** on all four architectures (amd64 `E9`,
|
||||||
|
arm64 `B`, riscv64 `JAL X0`, loong64 `B`) with the call relocation.
|
||||||
|
- **Live oracle-parity tests.** Kernel files covering every guard
|
||||||
|
class, large-offset pattern and tail call are assembled by gasm and
|
||||||
|
by the installed `go tool asm` and compared byte-for-byte on all four
|
||||||
|
architectures, alongside the existing pinned-byte tests.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The v0.32.0 review findings: the parser rejects malformed `TEXT`
|
||||||
|
frames and parses signed frame sizes; amd64 frame adjustments above
|
||||||
|
127 bytes encode with imm32; arm64 and loong64 relocation encodings
|
||||||
|
match the toolchain; the linter guards unnamed `TEXT` directives and
|
||||||
|
refreshes its textflag table; the LSP recovers from handler panics
|
||||||
|
and decodes client URIs; watchpoint slot state moved into the debug
|
||||||
|
session; dead verify code removed; em and en dashes replaced across
|
||||||
|
sources.
|
||||||
|
- `gasm asm --format goobj`: internal calls to `TEXT` symbols of the
|
||||||
|
same file resolve on every architecture (the reference check accepted
|
||||||
|
only the amd64 call kind).
|
||||||
|
- `gasm asm --format elf` on loong64: branch relocations now map to
|
||||||
|
`R_LARCH_B26` instead of falling into `R_LARCH_PCALA_HI20`.
|
||||||
|
- arm64 large-prologue `ADD`/`SUB` use the extended-register encoding
|
||||||
|
the toolchain picks, and the morestack block saves the link register
|
||||||
|
with the toolchain's `OR` form on loong64.
|
||||||
|
|
||||||
## [0.32.0] — 2026-08-31
|
## [0.32.0] — 2026-08-31
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ developer tooling to Plan 9 assembly on amd64, arm64, riscv64 and loong64.
|
|||||||
directly.
|
directly.
|
||||||
- **Formatter.** `gasm fmt` canonicalises indentation, operand spacing,
|
- **Formatter.** `gasm fmt` canonicalises indentation, operand spacing,
|
||||||
per-function mnemonic alignment and blank-line layout: `gofmt` for assembly,
|
per-function mnemonic alignment and blank-line layout: `gofmt` for assembly,
|
||||||
operating recursively on directories the way `go fmt` does.
|
operating recursively on directories the way `go fmt` does. `-l` lists
|
||||||
|
files whose formatting differs and `-d` prints a unified diff.
|
||||||
- **Linter.** `gasm lint` runs 18 conservative static checks, among them
|
- **Linter.** `gasm lint` runs 18 conservative static checks, among them
|
||||||
`undefined-label`, `abi-argsize` (declared frame vs the `// func` signature),
|
`undefined-label`, `abi-argsize` (declared frame vs the `// func` signature),
|
||||||
`register-clobber` (Go ABI register liveness over the control-flow graph),
|
`register-clobber` (Go ABI register liveness over the control-flow graph),
|
||||||
@@ -24,7 +25,11 @@ developer tooling to Plan 9 assembly on amd64, arm64, riscv64 and loong64.
|
|||||||
- **Standalone assembler.** `gasm asm` encodes all four architectures without
|
- **Standalone assembler.** `gasm asm` encodes all four architectures without
|
||||||
the Go toolchain and writes raw images, linkable ELF objects (with DWARF5
|
the Go toolchain and writes raw images, linkable ELF objects (with DWARF5
|
||||||
debug sections) or the Go toolchain's own GOOBJ format, which `go build`
|
debug sections) or the Go toolchain's own GOOBJ format, which `go build`
|
||||||
consumes in place of the toolchain's output.
|
consumes in place of the toolchain's output. Framed functions get the
|
||||||
|
stack-split guard and the morestack block, byte-identical to the
|
||||||
|
toolchain's, so split functions link too.
|
||||||
|
- **Disassembler.** `gasm dis` lists a `.s` file's functions at their real
|
||||||
|
offsets after assembling, or disassembles raw bytes from a file or stdin.
|
||||||
- **Dynamic verification.** `gasm verify` JIT-loads assembled functions into
|
- **Dynamic verification.** `gasm verify` JIT-loads assembled functions into
|
||||||
executable memory: smoke calls, ABI checks (sentinel registers, red-zone
|
executable memory: smoke calls, ABI checks (sentinel registers, red-zone
|
||||||
canary), differential fuzzing against the `go tool asm` build, and
|
canary), differential fuzzing against the `go tool asm` build, and
|
||||||
@@ -36,7 +41,8 @@ developer tooling to Plan 9 assembly on amd64, arm64, riscv64 and loong64.
|
|||||||
push and pull diagnostics, semantic-token highlighting, go-to-definition,
|
push and pull diagnostics, semantic-token highlighting, go-to-definition,
|
||||||
find references, rename, formatting, inlay hints, code actions, signature
|
find references, rename, formatting, inlay hints, code actions, signature
|
||||||
help, document highlights, workspace symbol search, #include document
|
help, document highlights, workspace symbol search, #include document
|
||||||
links and folding ranges over stdio.
|
links and folding ranges over stdio; definition, references and rename
|
||||||
|
work across every open document.
|
||||||
- **Comparators and audits.** `gasm diff` compares the machine code of two
|
- **Comparators and audits.** `gasm diff` compares the machine code of two
|
||||||
assembly files byte-for-byte, `gasm profile` shows basic-block structure,
|
assembly files byte-for-byte, `gasm profile` shows basic-block structure,
|
||||||
`gasm audit-instructions` diffs the encoder against the installed toolchain,
|
`gasm audit-instructions` diffs the encoder against the installed toolchain,
|
||||||
@@ -102,9 +108,13 @@ gasm verify --call add --args a=2,b=3 hello_amd64.s # JIT-call it with argumen
|
|||||||
```sh
|
```sh
|
||||||
gasm fmt # reformat every .s below here, like go fmt
|
gasm fmt # reformat every .s below here, like go fmt
|
||||||
gasm fmt -w kernel_amd64.s # canonicalise one file in place
|
gasm fmt -w kernel_amd64.s # canonicalise one file in place
|
||||||
|
gasm fmt -l *.s # list files whose formatting differs
|
||||||
|
gasm fmt -d kernel_amd64.s # print a unified diff instead
|
||||||
gasm lint *.s # static checks
|
gasm lint *.s # static checks
|
||||||
gasm asm --format elf -o k.o k.s # assemble to a linkable ELF object
|
gasm asm --format elf -o k.o k.s # assemble to a linkable ELF object
|
||||||
gasm asm --format goobj -p pkg/path -o k.o k.s # Go object, consumed by go build
|
gasm asm --format goobj -p pkg/path -o k.o k.s # Go object, consumed by go build
|
||||||
|
gasm dis k.s # assemble, then list each function
|
||||||
|
gasm dis -a amd64 - < dump.bin # disassemble raw bytes from stdin
|
||||||
gasm verify --ground-truth k.s # byte-for-byte vs go tool asm
|
gasm verify --ground-truth k.s # byte-for-byte vs go tool asm
|
||||||
gasm verify --fuzz k.s # differential fuzz vs the go tool asm build
|
gasm verify --fuzz k.s # differential fuzz vs the go tool asm build
|
||||||
gasm debug --func name k.s # interactive debugger
|
gasm debug --func name k.s # interactive debugger
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ import (
|
|||||||
|
|
||||||
// version is the release version, stamped at build time via
|
// version is the release version, stamped at build time via
|
||||||
// -ldflags "-X main.version=…" (defaulting to the current release).
|
// -ldflags "-X main.version=…" (defaulting to the current release).
|
||||||
var version = "0.32.0"
|
var version = "0.33.0"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
|
|||||||
@@ -237,6 +237,18 @@ STP+SUB for large frames) and SB/global symbol references (ADRP+ADD pairs with
|
|||||||
R_ADDRARM64 relocations). Like the other encoders it is validated
|
R_ADDRARM64 relocations). Like the other encoders it is validated
|
||||||
byte-for-byte against `GOARCH=arm64 go tool asm`.
|
byte-for-byte against `GOARCH=arm64 go tool asm`.
|
||||||
|
|
||||||
|
On top of the per-architecture encoders, every framed function carries the
|
||||||
|
**stack-split guard**: the prologue check against `g.stackguard0` (small,
|
||||||
|
medium and large frame classes, the medium and large classes materialising
|
||||||
|
their offset through the architecture's temporary register and the large
|
||||||
|
class adding the SP-underflow branch) and the trailing morestack block
|
||||||
|
(save the link register, `CALL runtime.morestack_noctxt`, jump back to the
|
||||||
|
function entry). The auto-NOSPLIT rule, the frame classes, the large-frame
|
||||||
|
prologue and epilogue forms and the tail calls match the toolchain's
|
||||||
|
`stacksplit` and `preprocess` output byte for byte; a parity suite
|
||||||
|
assembles kernel files with gasm and the installed `go tool asm` and diffs
|
||||||
|
the bytes on all four architectures.
|
||||||
|
|
||||||
On top of the encoder, `Assemble` walks a parsed `TEXT` body, converts each
|
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
|
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
|
resolve to relative jump offsets: jumps start in the short (rel8) form and
|
||||||
|
|||||||
+18
-1
@@ -22,7 +22,7 @@ one token per line. FILE may be `-` to read standard input.
|
|||||||
Parse FILE and report syntax errors on stderr. On success, prints how
|
Parse FILE and report syntax errors on stderr. On success, prints how
|
||||||
many declarations and TEXT functions the file contains.
|
many declarations and TEXT functions the file contains.
|
||||||
|
|
||||||
## `gasm fmt [-w] [path...]`
|
## `gasm fmt [-w|-l|-d] [path...]`
|
||||||
|
|
||||||
Canonicalise the formatting of Plan 9 assembly sources: indentation,
|
Canonicalise the formatting of Plan 9 assembly sources: indentation,
|
||||||
operand spacing, per-function mnemonic alignment, and blank-line layout.
|
operand spacing, per-function mnemonic alignment, and blank-line layout.
|
||||||
@@ -30,6 +30,8 @@ operand spacing, per-function mnemonic alignment, and blank-line layout.
|
|||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `-w` | Write result to the source file (default: print to stdout) |
|
| `-w` | Write result to the source file (default: print to stdout) |
|
||||||
|
| `-l` | List files whose formatting differs, one per line; write nothing |
|
||||||
|
| `-d` | Print a unified diff of the canonical formatting instead |
|
||||||
|
|
||||||
With no arguments, or with a directory argument, every `.s` file below
|
With no arguments, or with a directory argument, every `.s` file below
|
||||||
it is reformatted in place and the names of changed files are listed
|
it is reformatted in place and the names of changed files are listed
|
||||||
@@ -62,6 +64,21 @@ Assemble FILE to machine code (amd64, arm64, riscv64, loong64).
|
|||||||
| `-p` | Package path (required for `--format goobj`) |
|
| `-p` | Package path (required for `--format goobj`) |
|
||||||
| `-o` | Write output to file (default: hex dump to stdout) |
|
| `-o` | Write output to file (default: hex dump to stdout) |
|
||||||
|
|
||||||
|
## `gasm dis [-a arch] <file>`
|
||||||
|
|
||||||
|
Disassemble machine code to instruction text (via `golang.org/x/arch`).
|
||||||
|
|
||||||
|
With a `.s` file, the file is assembled first and the listing follows the
|
||||||
|
real layout: one block per `TEXT` function, local labels printed at their
|
||||||
|
offsets. The architecture comes from the file name suffix, or from `-a`.
|
||||||
|
With any other file, or `-` for standard input, the bytes are
|
||||||
|
disassembled linearly and `-a` selects the architecture (amd64, arm64,
|
||||||
|
riscv64 or loong64).
|
||||||
|
|
||||||
|
| Flag | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `-a` | Architecture for raw input without a `_arch.s` name |
|
||||||
|
|
||||||
## `gasm verify [flags] <file.s>`
|
## `gasm verify [flags] <file.s>`
|
||||||
|
|
||||||
Assemble FILE, map it into executable memory, and run dynamic checks.
|
Assemble FILE, map it into executable memory, and run dynamic checks.
|
||||||
|
|||||||
Reference in New Issue
Block a user