Repository: go
Issue: cmd/nm: running nm on object from different version can crash
Labels: NeedsFix,compiler/runtime

### Go version

tip

### Output of `go env` in your module/workspace:

```shell
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/iant/.cache/go-build'
GOENV='/home/iant/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/iant/gopath/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/iant/gopath'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org'
GOROOT='/home/iant/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/iant/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.24-bae2e968e2 Mon Sep 30 22:04:40 2024 +0000'
GODEBUG=''
GOTELEMETRY='on'
GOTELEMETRYDIR='/home/iant/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/iant/go/src/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1550637861=/tmp/go-build -gno-record-gcc-switches'
```


### What did you do?

Where go is current go tip (version go1.24-bae2e968e2) and ~/go1.23/bin/go is go 1.23 (version 1.23.2):

```
> cat foo.go
package p

func F() any {
	return struct{ p *error}{nil}
}
> go build -o foo.a foo.go
> ~/go1.23/bin/go tool nm foo.a
panic: runtime error: index out of range [255] with length 255

goroutine 1 [running]:
cmd/internal/goobj.BuiltinName(...)
	cmd/internal/goobj/builtin.go:22
cmd/internal/objfile.(*goobjFile).symbols.func2({0x5502a0?, 0x0?})
	cmd/internal/objfile/goobj.go:143 +0x35a
cmd/internal/objfile.(*goobjFile).symbols(0xc0000aa380?)
	cmd/internal/objfile/goobj.go:199 +0xdb0
cmd/internal/objfile.(*Entry).Symbols(0x7ffdf24635a2?)
	cmd/internal/objfile/objfile.go:130 +0x1c
main.nm({0x7ffdf24635a2, 0x5})
	cmd/nm/nm.go:120 +0x1d1
main.main()
	cmd/nm/nm.go:92 +0x2b1
```

### What did you see happen?

Running go1.23 tool nm on an object created by go tip crashed.

### What did you expect to see?

I expected to see an error, or ordinary nm output.  I did not expect to see a crash.

Since making nm forward compatible seems infeasible, we should change it so that if run on a newer object version it reports an error and exits, rather than crashing.

The object file format already has a magic number that supports this (cmd/internal/goobj.Magic).  That magic number is normally changed when the object file format changes.  In this case what happened is that the list of builtin names changed.  That is part of the object file format, because the index into the builtin name slice is stored in the file format (when the symbol `PkgIdx` is `goobj.PkgIdxBuiltin`, the symbol `SymIdx` is an index into `goobj.builtins`).

Perhaps we should make cmd/internal/goobj/mkbuiltin.go automatically update the magic number.  Or at least print a message saying that the magic number should be updated.  Or perhaps we need some different mechanism, like a hash of the builtin names.

CC @golang/compiler