Commit 7820d270 authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle Committed by Ian Lance Taylor

cmd/internal/gc, cmd/internal/ld: fixes for global vars of types from other modules

To make the gcprog for global data containing variables of types defined in other shared
libraries, we need to know a lot about those types. So read the value of any symbol with
a name starting with "type.". If a type uses a mask, the name of the symbol defining the
mask unfortunately cannot be predicted from the type name so I have to keep track of the
addresses of every such symbol and associate them with the type symbols after the fact.

I'm not very happy about this change, but something like this is needed and this is as
pleasant as I know how to make it.

Change-Id: I408d831b08b3b31e0610688c41367b23998e975c
Reviewed-on: https://go-review.googlesource.com/8334Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
parent ac1cdd13
......@@ -67,10 +67,20 @@ func decodetype_size(s *LSym) int64 {
// Type.commonType.gc
func decodetype_gcprog(s *LSym) *LSym {
if s.Type == obj.SDYNIMPORT {
// The gcprog for "type.$name" is calle "type..gcprog.$name".
x := "type..gcprog." + s.Name[5:]
return Linklookup(Ctxt, x, 0)
}
return decode_reloc_sym(s, 1*int32(Thearch.Ptrsize)+8+2*int32(Thearch.Ptrsize))
}
func decodetype_gcmask(s *LSym) []byte {
if s.Type == obj.SDYNIMPORT {
// ldshlibsyms makes special efforts to read the value
// of gcmask for types defined in that shared library.
return s.gcmask
}
mask := decode_reloc_sym(s, 1*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
return mask.P
}
......
......@@ -1136,11 +1136,23 @@ func ldshlibsyms(shlib string) {
return
}
defer f.Close()
syms, err := f.DynamicSymbols()
syms, err := f.Symbols()
if err != nil {
Diag("cannot read symbols from shared library: %s", libpath)
return
}
// If a package has a global variable of a type defined in another shared
// library, we need to know the gcmask used by the type, if any. To support
// this, we read all the runtime.gcbits.* symbols, keep a map of address to
// gcmask, and after we're read all the symbols, read the addresses of the
// gcmasks symbols out of the type data to look up the gcmask for each type.
// This depends on the fact that the runtime.gcbits.* symbols are local (so
// the address is actually present in the type data and we don't have to
// search all relocations to find the ones which correspond to gcmasks) and
// also that the shared library we are linking against has not had the symbol
// table removed.
gcmasks := make(map[uint64][]byte)
types := []*LSym{}
for _, s := range syms {
if elf.ST_TYPE(s.Info) == elf.STT_NOTYPE || elf.ST_TYPE(s.Info) == elf.STT_SECTION {
continue
......@@ -1151,6 +1163,20 @@ func ldshlibsyms(shlib string) {
if strings.HasPrefix(s.Name, "_") {
continue
}
if strings.HasPrefix(s.Name, "runtime.gcbits.0x") {
data := make([]byte, s.Size)
sect := f.Sections[s.Section]
if sect.Type == elf.SHT_PROGBITS {
n, err := sect.ReadAt(data, int64(s.Value-sect.Offset))
if uint64(n) != s.Size {
Diag("Error reading contents of %s: %v", s.Name, err)
}
}
gcmasks[s.Value] = data
}
if elf.ST_BIND(s.Info) != elf.STB_GLOBAL {
continue
}
lsym := Linklookup(Ctxt, s.Name, 0)
if lsym.Type != 0 && lsym.Dupok == 0 {
Diag(
......@@ -1159,6 +1185,35 @@ func ldshlibsyms(shlib string) {
}
lsym.Type = obj.SDYNIMPORT
lsym.File = libpath
if strings.HasPrefix(lsym.Name, "type.") {
data := make([]byte, s.Size)
sect := f.Sections[s.Section]
if sect.Type == elf.SHT_PROGBITS {
n, err := sect.ReadAt(data, int64(s.Value-sect.Offset))
if uint64(n) != s.Size {
Diag("Error reading contents of %s: %v", s.Name, err)
}
lsym.P = data
}
if !strings.HasPrefix(lsym.Name, "type..") {
types = append(types, lsym)
}
}
}
for _, t := range types {
if decodetype_noptr(t) != 0 || decodetype_usegcprog(t) != 0 {
continue
}
// The expression on the next line is a copy of the expression from
// decodetype_gcmask in decodesym.go, which in turn depends on details of
// how the type data is laid out, as seen in gc/reflect.go:dcommontype.
addr := decode_inuxi(t.P[1*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize)
tgcmask, ok := gcmasks[addr]
if !ok {
Diag("bits not found for %s at %d", t.Name, addr)
}
t.gcmask = tgcmask
}
// We might have overwritten some functions above (this tends to happen for the
......
......@@ -75,6 +75,7 @@ type LSym struct {
P []byte
R []Reloc
Local bool
gcmask []byte
}
type Reloc struct {
......
......@@ -340,6 +340,8 @@ func rdsym(ctxt *Link, f *Biobuf, pkg string) *LSym {
s.Reachable = false
}
}
if v == 0 && strings.HasPrefix(s.Name, "runtime.gcbits.0x") {
s.Local = true
}
return s
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment