Repository navigation
[AUTOMATED] Name static Go itabs as go:itab.<concrete>,<interface> data symbols - #1544
Merged
Merged
Conversation
…ta symbols (rides gotypeglobals) Repro: kuna decompile-all hello.stripped --option gotypeglobals off | grep -c 'go:itab\.' # 0 kuna decompile-all hello.stripped | grep -c 'go:itab\.' # 57 A Go binary's interface-dispatch tables (itabs) are reachable through the moduledata but lose their `go:itab.<concrete>,<interface>` linker names when the image is stripped, so every interface conversion renders its itab operand as a bare `dat_<addr>`. This teaches the gotypes harvest — the second consumer after gotypeglobals' type descriptors — to reinstate those names. Each static itab is located per toolchain era: the go1.18..1.25 `itablinks` pointer slice in the moduledata, or the go1.26+ `[types + itaboffset, + itabsize)` contiguous region walked by each record's `ITab.Size()`. The two type names are built from the two descriptor ADDRESSES the record points at (Inter at offset 0, Type at offset 8), resolved through the already-decoded `[types, etypes)` blob — never from a spelled type name (the #1542 lesson: bind by descriptor address). The itab becomes a NAME-only data symbol, not a typed object: an itab address is used polymorphically (passed to getitab, compared, stored into an interface word), so locking its global to a struct type would demote those uses and hide the very symbol a reference renders — exactly how Go's own symtab names an itab untyped. An itab the image already names (an unstripped binary's symbol table) is left to that name via an occupied-address filter, so the pass only ever ADDS the names stripping removed; it never overrides or loses an existing one. Rides the existing `gotypeglobals` option (no new option, no catalog count change): the same gate commits both descriptor globals and itab names, so `gotypeglobals off` is byte-identical to before and non-Go images never see it. Measured (fresh build): stripped additive: hello 0->57 itab refs (15 distinct), gofmt 0->852 (358) unstripped no-loss: gofmt 184 distinct names OFF==ON (LOST=0, ADDED=0), hello 0->10 (additive, LOST=0) Gates: make test 675/675, make test-stages 4047/4047, make rust-test exit 0 (under vendored go 1.22; the system go 1.18 fails unrelated Go-build tests), make check-spec OK, kuna catalog --check OK. Three-toolchain e2e witness (go1.22/1.25/1.27) plus hermetic unit tests on synthetic itab blobs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A stripped Go binary's interface dispatch referenced anonymous addresses — the itab (interface-table) records that bind a concrete type to an interface rendered as
dat_<addr>:The fix (rides
gotypeglobals#1540 — no new option):go:itab.<concrete>,<interface>named data symbol. The two type names come from the two descriptor addresses the record points at (offsets 0 and 8), resolved through the already-decoded type blob — never from a spelled name (the [AUTOMATED] Per-call-site output type lock + Go allocation result typing (sitetypelock, gonewtype) #1542 lesson);Interis validatedKIND_INTERFACEand both descriptors must land in the type blob or the record is rejected.itablinksslice (go1.18–1.25) or the contiguous[types+itaboffset, …)region go1.26+ walks record-by-record (the same restructuring as [AUTOMATED] Walk go1.26+'s descriptor region: moduledata moved and the typelinks slice is gone #1285's typelinks change), with the era-stableinternal/abi.ITablayout.Measured (stripped, additive): hello 0→57 itab refs, gofmt 0→852 (358 distinct);
gotypeglobals offemits zero (byte-identical to pre-change); unstripped off==on, zero names lost.Tests:
verify_gotypes::stripped_go_itab_renders_namedgreen under go1.22/1.25/1.27; 5 hermetic unit tests on synthetic itab blobs (both locate paths, the garbage-stop, the method-tail size). Datatests 675/675 and stages unchanged.🤖 Generated with Claude Code