Skip to content

Commit 8b07ec2

Browse files
committed
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 <[email protected]> Reviewed-by: David Crawshaw <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent aabdb66 commit 8b07ec2

File tree

4 files changed

+21
-2
lines changed

4 files changed

+21
-2
lines changed

misc/cgo/testshared/src/depBase/dep.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package depBase
22

3+
import (
4+
"os"
5+
"reflect"
6+
)
7+
38
var V int = 1
49

510
var HasMask []string = []string{"hi"}
@@ -13,6 +18,10 @@ type Dep struct {
1318
}
1419

1520
func (d *Dep) Method() int {
21+
// This code below causes various go.itab.* symbols to be generated in
22+
// the shared library. Similar code in ../exe/exe.go results in
23+
// exercising https://github.com/golang/go/issues/17594
24+
reflect.TypeOf(os.Stdout).Elem()
1625
return 10
1726
}
1827

misc/cgo/testshared/src/exe/exe.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@ package main
22

33
import (
44
"depBase"
5+
"os"
6+
"reflect"
57
"runtime"
68
)
79

810
func main() {
911
defer depBase.ImplementedInAsm()
12+
// This code below causes various go.itab.* symbols to be generated in
13+
// the executable. Similar code in ../depBase/dep.go results in
14+
// exercising https://github.com/golang/go/issues/17594
15+
reflect.TypeOf(os.Stdout).Elem()
1016
runtime.GC()
1117
depBase.V = depBase.F() + 1
1218
}

src/cmd/compile/internal/gc/reflect.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,11 +1395,11 @@ func dumptypestructs() {
13951395
o += len(imethods(i.itype)) * Widthptr // skip fun method pointers
13961396
// at runtime the itab will contain pointers to types, other itabs and
13971397
// method functions. None are allocated on heap, so we can use obj.NOPTR.
1398-
ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR))
1398+
ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR|obj.LOCAL))
13991399

14001400
ilink := Pkglookup(i.t.tconv(FmtLeft)+","+i.itype.tconv(FmtLeft), itablinkpkg)
14011401
dsymptr(ilink, 0, i.sym, 0)
1402-
ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
1402+
ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA|obj.LOCAL))
14031403
}
14041404

14051405
// process ptabs

src/runtime/iface.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ func additab(m *itab, locked, canfail bool) {
138138
throw("invalid itab locking")
139139
}
140140
h := itabhash(inter, typ)
141+
if m == hash[h] {
142+
println("duplicate itab for", typ.string(), "and", inter.typ.string())
143+
throw("duplicate itabs")
144+
}
141145
m.link = hash[h]
142146
atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m))
143147
}

0 commit comments

Comments
 (0)