65 lines
3.2 KiB
Markdown
65 lines
3.2 KiB
Markdown
# Deferred decisions
|
|
|
|
Design decisions deliberately postponed, with enough context to pick them up
|
|
again without re-deriving the analysis. Each entry records what is deferred,
|
|
why, the options on the table, and the trigger that should reopen it.
|
|
|
|
---
|
|
|
|
## GOOBJ external (cross-package) symbol references
|
|
|
|
**Status:** resolved (v0.29.0+, 2026-08-07).
|
|
|
|
**Approach taken.** Instead of parsing the compiler's iexport data (which
|
|
would have required either `golang.org/x/tools` or an in-house parser), the
|
|
resolver reads the **GOOBJ data directly** from the target package's `.a`
|
|
archive. The `.a` file contains a `_go_.o` member whose GOOBJ s is the
|
|
same one gasm writes — the parser reuses the same layout (`blkSymdef`,
|
|
`blkNonpkgdef`, the string table), so no new dependency was needed.
|
|
|
|
**How it works.**
|
|
|
|
1. `go list -json -export <pkg>` finds the target package's `.a` file.
|
|
2. `extractGOOBJ` reads the ar archive, finds the `_go_.o` member, skips
|
|
the `"go object …\n!\n"` preamble and parses the GOOBJ header.
|
|
3. `goobjFile.symbols()` walks `blkSymdef` and `blkNonpkgdef` in definition
|
|
order — the same order the linker uses — to build the symbol → index
|
|
mapping.
|
|
4. `resolveExternalSymbols` wires the resolved `{PkgIdx, SymIdx}` into the
|
|
GOOBJ emission.
|
|
|
|
The resolver is invoked automatically when `img.Externals` is non-empty; it
|
|
runs `go list` as a subprocess (consistent with `toolchainObjectPreamble`
|
|
which already calls `go tool asm`). All symbol data is cached per package
|
|
for the lifetime of the GOOBJ emission.
|
|
|
|
## 2026-08-29 tooling round
|
|
|
|
- `lint abi0-register-args`: flags kernels whose `// func` parameters are
|
|
never read from the FP frame. Motivated by a real latent bug: kernels
|
|
reading arguments from registers pass every test while the autogenerated
|
|
`F.abi0` wrapper happens to leave the caller's register values intact, and
|
|
break on a toolchain upgrade.
|
|
- `lint nonportable-register-name`: the RAX/EAX register spellings are a gasm
|
|
extension; go tool asm rejects them, so files using them only link through
|
|
the gasm goobj path.
|
|
- `lint unencodable-instruction`: a mnemonic in the architecture table that
|
|
`asm.Encodable` rejects is flagged at edit time instead of failing at
|
|
assembly time.
|
|
- `audit-instructions`: black-box diff of the encoder against go tool asm.
|
|
As of this round the tables fully overlap on names; the audit exists to
|
|
catch drift in both directions (future supersets and future gaps).
|
|
- `scaffold differential`: generates the direct-call differential skeleton
|
|
(two independent seed sets, output and in-place buffer comparison) that a
|
|
pipeline-level fuzz can never replace.
|
|
- `verify --args`: scalar arguments for `-call`, closing the repro gap where
|
|
only buffers could be supplied.
|
|
- `debug --script/--timeout/--cover`: headless debugging with a watchdog
|
|
armed before the ptrace attach (untracing sandboxes hang the attach), and
|
|
label-level block coverage for the "did my test ever enter that branch"
|
|
question.
|
|
- Superset policy remains: gasm may accept spellings and encodings go tool
|
|
asm lacks, but such kernels ship only via `gasm asm --format goobj`; the
|
|
audit reports the superset surface. The register-alias superset is warned
|
|
about by lint because the default `go build` path cannot consume it.
|