Skip to content

tests, tools: every inline-asm LVO call lists all four scratch registers; CI gate (#70) - #86

Merged
tinic merged 1 commit into
mainfrom
fix/70-lvo-clobber-gate
Sep 26, 2026
Merged

tinic merged 1 commit into
mainfrom
fix/70-lvo-clobber-gate

Conversation

@tinic

@tinic tinic commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Fixes #70

Steps 2 and 3 of #70: the scanner is a CI gate, and the remaining test sites are fixed.

Gate. tools/check-lvo-clobbers.sh runs tools/check-lvo-clobbers.py over src/ and tests/. It flags every extended asm statement that calls through a6 and does not list d0, d1, a0 and a1 as outputs or clobbers. It reads register declarations through object-like macros (BSD_SCRATCH, NETDEV_REG_A1) from the file and from its "..." includes, and it skips top-level asm. Output is key=value, and the exit code is 1 on any flagged site. The gate runs in stage_host next to check-lvo-matrix.sh, is registered in check-gates-wired.sh, and is on the shellcheck list.

Validation

tree statements flagged
58c5c4f (the tree the issue scanned) 415 31
main 7fa3df3 (before) 415 14
this branch (after) 415 0
src/tools/toolsock.c alone 22 0
  • On 58c5c4f, all 16 shipped sites are flagged with exactly the missing sets the issue lists, and tests/sockopt/sockopt_test.c:332 (pre-sockopt_test: the recvfrom helper declares a1 clobbered #68) is flagged missing=a1.
  • The issue's 77 included 46 false positives:
    • 43 BSD_SCRATCH macro sites in ipv6_socket_test, sockopt_test and udpdrill
    • apidrill's TH() macro, which lists all eight registers
    • the top-level asm in genet.c:542 and netdev_cache.c:85

Fixes (14 test sites). A missing register that is also an input becomes an output: a dummy "=r", or "+r" as in #71. A missing register that is not an input becomes a clobber.

  • atf_main:64 (a0, d0)
  • tickprobe:120 (d1)
  • endurance:118 (d1)
  • ipv6_socket_test:667 (d0)
  • refused_leak_test:98 (d1)
  • tcpdrill:156 and :266 (d1)
  • tls_loop:270 (d1)
  • cardgrab:66 and :80 (a1)
  • ifprobe:829 and :844 (a0)
  • udpdrill:195 and :277 (a1). These are the sockopt_test: the recvfrom helper declares a1 clobbered #68 recvfrom/getsockopt shape.

Repro: tools/check-lvo-clobbers.sh; echo $?

🤖 Generated with Claude Code

…ers; CI gate (#70)

An LVO may destroy d0, d1, a0 and a1.  An extended asm statement that
lists one of them only as an input lets GCC reuse a value the call has
overwritten, which is how #68 passed a stale recvfrom address.

tools/check-lvo-clobbers.sh (python in check-lvo-clobbers.py) scans
src/ and tests/ for asm statements whose template calls through a6
and reports each one whose outputs and clobbers leave out a scratch
register.  It reads register declarations through object-like macros
(BSD_SCRATCH, NETDEV_REG_A1) from the file and its "..." includes, and
skips top-level asm.  Output is key=value, exit 1 on any site.  It is
wired into stage_host next to check-lvo-matrix.sh, registered in
check-gates-wired.sh, and added to the shellcheck list.

Validation:
  58c5c4f (the tree the issue scanned): 415 statements, 31 flagged.
  All 16 shipped sites match the issue's missing sets exactly, and
  tests/sockopt/sockopt_test.c:332 (pre-#68) is flagged missing=a1.
  src/tools/toolsock.c alone: 22 statements, 0 flagged.
  The issue's 77 included 46 false positives: 43 BSD_SCRATCH macro
  sites, apidrill's TH() macro, and the top-level asm in genet.c and
  netdev_cache.c.

The 14 real test sites on main are fixed: a register that is also an
input becomes an output (dummy "=r", or "+r" as in #71), one that is
not becomes a clobber.  udpdrill's recvfrom and getsockopt helpers had
the #68 shape (a1).

  before (7fa3df3): statements=415 files=50 flagged=14
  after:             statements=415 files=50 flagged=0

Fixes #70

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tinic
tinic merged commit 342de74 into main Sep 26, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inline-asm LVO calls omit scratch-register clobbers: 77 sites, 2 REAL in shipped binaries (#68 class)

1 participant