golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.12k stars 17.68k forks source link

cmd/nm: running nm on object from different version can crash #69928

Open ianlancetaylor opened 1 month ago

ianlancetaylor commented 1 month ago

Go version

tip

Output of go env in your module/workspace:

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

gabyhelp commented 1 month ago

Related Issues and Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

cherrymui commented 1 month ago

Yeah, we should update the magic number. And it is a good idea to have mkbuiltin.go automatically updates it.

gopherbot commented 4 days ago

Change https://go.dev/cl/627417 mentions this issue: cmd/internal/goobj: make mkbuiltin.go automatically update Magic const