mirror of https://github.com/golang/go.git
cmd/go/internal/modload: ensure that __debug_modinfo__ is not discarded during linking
Fixes #28753 Updates #29628 Change-Id: I4a561be7d491a0d088e656b00151ae1bdbd16a84 Reviewed-on: https://go-review.googlesource.com/c/158357 Run-TryBot: Bryan C. Mills <bcmills@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
193c16a364
commit
9d23975d89
|
|
@ -252,10 +252,19 @@ func findModule(target, path string) module.Version {
|
|||
func ModInfoProg(info string) []byte {
|
||||
// Inject a variable with the debug information as runtime/debug.modinfo,
|
||||
// but compile it in package main so that it is specific to the binary.
|
||||
// No need to populate it in an init func; it will still work with go:linkname.
|
||||
//
|
||||
// The variable must be a literal so that it will have the correct value
|
||||
// before the initializer for package main runs.
|
||||
//
|
||||
// We also want the value to be present even if runtime/debug.modinfo is
|
||||
// otherwise unused in the rest of the program. Reading it in an init function
|
||||
// suffices for now.
|
||||
|
||||
return []byte(fmt.Sprintf(`package main
|
||||
import _ "unsafe"
|
||||
//go:linkname __debug_modinfo__ runtime/debug.modinfo
|
||||
var __debug_modinfo__ = %q
|
||||
var keepalive_modinfo = __debug_modinfo__
|
||||
func init() { keepalive_modinfo = __debug_modinfo__ }
|
||||
`, string(infoStart)+info+string(infoEnd)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,34 +7,83 @@ cd x
|
|||
go mod edit -require=rsc.io/quote@v1.5.2
|
||||
go mod edit -replace=rsc.io/quote@v1.5.2=rsc.io/quote@v1.0.0
|
||||
|
||||
go run main.go
|
||||
|
||||
stderr 'Hello, world.'
|
||||
# Build a binary and ensure that it can output its own debug info.
|
||||
# The debug info should be accessible before main starts (golang.org/issue/29628).
|
||||
go build
|
||||
exec ./x$GOEXE
|
||||
stderr 'mod\s+x\s+\(devel\)'
|
||||
stderr 'dep\s+rsc.io/quote\s+v1.5.2\s+'
|
||||
stderr '=>\s+rsc.io/quote\s+v1.0.0\s+h1:'
|
||||
stderr 'Hello, world.'
|
||||
|
||||
[short] skip
|
||||
|
||||
# Build a binary that accesses its debug info by reading the binary directly
|
||||
# (rather than through debug.ReadBuildInfo).
|
||||
# The debug info should still be present (golang.org/issue/28753).
|
||||
cd unused
|
||||
go build
|
||||
exec ./unused$GOEXE
|
||||
|
||||
-- x/go.mod --
|
||||
module x
|
||||
|
||||
-- x/lib/lib.go --
|
||||
// Package lib accesses runtime/debug.modinfo before package main's init
|
||||
// functions have run.
|
||||
package lib
|
||||
|
||||
import "runtime/debug"
|
||||
|
||||
func init() {
|
||||
m, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
panic("failed debug.ReadBuildInfo")
|
||||
}
|
||||
println("mod", m.Main.Path, m.Main.Version)
|
||||
for _, d := range m.Deps {
|
||||
println("dep", d.Path, d.Version, d.Sum)
|
||||
if r := d.Replace; r != nil {
|
||||
println("=>", r.Path, r.Version, r.Sum)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- x/main.go --
|
||||
package main
|
||||
|
||||
import "runtime/debug"
|
||||
import "rsc.io/quote"
|
||||
import (
|
||||
"rsc.io/quote"
|
||||
_ "x/lib"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println(quote.Hello())
|
||||
|
||||
m, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
panic("failed debug.ReadBuildInfo")
|
||||
}
|
||||
println("mod", m.Main.Path, m.Main.Version)
|
||||
for _, d := range m.Deps {
|
||||
println("dep", d.Path, d.Version, d.Sum)
|
||||
if r := d.Replace; r != nil {
|
||||
println("=>", r.Path, r.Version, r.Sum)
|
||||
}
|
||||
}
|
||||
println(quote.Hello())
|
||||
}
|
||||
|
||||
-- x/unused/main.go --
|
||||
// The unused binary does not access runtime/debug.modinfo.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
_ "rsc.io/quote"
|
||||
)
|
||||
|
||||
func main() {
|
||||
b, err := ioutil.ReadFile(os.Args[0])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
infoStart, _ := hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
|
||||
if !bytes.Contains(b, infoStart) {
|
||||
log.Fatal("infoStart not found in binary")
|
||||
}
|
||||
log.Println("ok")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue