From: Michael Hudson-Doyle Date: Wed, 26 Oct 2016 02:57:58 +0000 (+1300) Subject: cmd/compile, runtime: make the go.itab.* symbols module-local X-Git-Tag: go1.8beta1~549 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=8b07ec20f7a971edce9eaf413b20e453c50858c6;p=gostls13.git cmd/compile, runtime: make the go.itab.* symbols module-local Otherwise, the way the ELF dynamic linker works means that you can end up with the same itab being passed to additab twice, leading to the itab linked list having a cycle in it. Add a test to additab in runtime to catch this when it happens, not some arbitrary and surprsing time later. Fixes #17594 Change-Id: I6c82edcc9ac88ac188d1185370242dc92f46b1ad Reviewed-on: https://go-review.googlesource.com/32131 Run-TryBot: Michael Hudson-Doyle Reviewed-by: David Crawshaw TryBot-Result: Gobot Gobot --- diff --git a/misc/cgo/testshared/src/depBase/dep.go b/misc/cgo/testshared/src/depBase/dep.go index c3ae96fe98..a518b4efe2 100644 --- a/misc/cgo/testshared/src/depBase/dep.go +++ b/misc/cgo/testshared/src/depBase/dep.go @@ -1,5 +1,10 @@ package depBase +import ( + "os" + "reflect" +) + var V int = 1 var HasMask []string = []string{"hi"} @@ -13,6 +18,10 @@ type Dep struct { } func (d *Dep) Method() int { + // This code below causes various go.itab.* symbols to be generated in + // the shared library. Similar code in ../exe/exe.go results in + // exercising https://github.com/golang/go/issues/17594 + reflect.TypeOf(os.Stdout).Elem() return 10 } diff --git a/misc/cgo/testshared/src/exe/exe.go b/misc/cgo/testshared/src/exe/exe.go index 136803fbc1..31fbedd31c 100644 --- a/misc/cgo/testshared/src/exe/exe.go +++ b/misc/cgo/testshared/src/exe/exe.go @@ -2,11 +2,17 @@ package main import ( "depBase" + "os" + "reflect" "runtime" ) func main() { defer depBase.ImplementedInAsm() + // This code below causes various go.itab.* symbols to be generated in + // the executable. Similar code in ../depBase/dep.go results in + // exercising https://github.com/golang/go/issues/17594 + reflect.TypeOf(os.Stdout).Elem() runtime.GC() depBase.V = depBase.F() + 1 } diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index da63f87c22..57192dec1c 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -1395,11 +1395,11 @@ func dumptypestructs() { o += len(imethods(i.itype)) * Widthptr // skip fun method pointers // at runtime the itab will contain pointers to types, other itabs and // method functions. None are allocated on heap, so we can use obj.NOPTR. - ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR)) + ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR|obj.LOCAL)) ilink := Pkglookup(i.t.tconv(FmtLeft)+","+i.itype.tconv(FmtLeft), itablinkpkg) dsymptr(ilink, 0, i.sym, 0) - ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA)) + ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA|obj.LOCAL)) } // process ptabs diff --git a/src/runtime/iface.go b/src/runtime/iface.go index b55a9ed893..f7ad40d1c0 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -138,6 +138,10 @@ func additab(m *itab, locked, canfail bool) { throw("invalid itab locking") } h := itabhash(inter, typ) + if m == hash[h] { + println("duplicate itab for", typ.string(), "and", inter.typ.string()) + throw("duplicate itabs") + } m.link = hash[h] atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m)) }