// 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
}
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
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(
}
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