package ld
-import "cmd/internal/obj"
+import (
+ "cmd/internal/obj"
+ "debug/elf"
+)
// Decoding the type.* symbols. This has to be in sync with
// ../../runtime/type.go, or more specifically, with what
return int64(decode_inuxi(s.P[Thearch.Ptrsize:], Thearch.Ptrsize)) // 0x8 / 0x10
}
+// Find the elf.Section of a given shared library that contains a given address.
+func findShlibSection(path string, addr uint64) *elf.Section {
+ for _, shlib := range Ctxt.Shlibs {
+ if shlib.Path == path {
+ for _, sect := range shlib.File.Sections {
+ if sect.Addr <= addr && addr <= sect.Addr+sect.Size {
+ return sect
+ }
+ }
+ }
+ }
+ return nil
+}
+
// Type.commonType.gc
-func decodetype_gcprog(s *LSym) *LSym {
+func decodetype_gcprog(s *LSym) []byte {
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)
+ addr := decodetype_gcprog_shlib(s)
+ sect := findShlibSection(s.File, addr)
+ if sect != nil {
+ // A gcprog is a 4-byte uint32 indicating length, followed by
+ // the actual program.
+ progsize := make([]byte, 4)
+ sect.ReadAt(progsize, int64(addr-sect.Addr))
+ progbytes := make([]byte, Ctxt.Arch.ByteOrder.Uint32(progsize))
+ sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
+ return append(progsize, progbytes...)
+ }
+ Exitf("cannot find gcprog for %s", s.Name)
+ return nil
}
- return decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
+ return decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize)).P
}
func decodetype_gcprog_shlib(s *LSym) uint64 {
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
+ addr := decodetype_gcprog_shlib(s)
+ ptrdata := decodetype_ptrdata(s)
+ sect := findShlibSection(s.File, addr)
+ if sect != nil {
+ r := make([]byte, ptrdata/int64(Thearch.Ptrsize))
+ sect.ReadAt(r, int64(addr-sect.Addr))
+ return r
+ }
+ Exitf("cannot find gcmask for %s", s.Name)
+ return nil
}
mask := decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
return mask.P
if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
Diag("reading %s from non-data section", sym.Name)
}
- n, err := sect.ReadAt(data, int64(sym.Value-sect.Offset))
+ n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
if uint64(n) != sym.Size {
Diag("reading contents of %s: %v", sym.Name, err)
}
Diag("cannot open shared library: %s", libpath)
return
}
- defer f.Close()
hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
if err != nil {
}
deps := strings.Split(string(depsbytes), "\n")
- syms, err := f.Symbols()
+ syms, err := f.DynamicSymbols()
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, "runtime.gcbits.") {
- gcmasks[s.Value] = readelfsymboldata(f, &s)
- }
- if elf.ST_BIND(s.Info) != elf.STB_GLOBAL {
- continue
- }
lsym := Linklookup(Ctxt, s.Name, 0)
if lsym.Type != 0 && lsym.Type != obj.SDYNIMPORT && lsym.Dupok == 0 {
Diag(
}
lsym.Type = obj.SDYNIMPORT
lsym.ElfType = elf.ST_TYPE(s.Info)
- lsym.File = libpath
- if strings.HasPrefix(lsym.Name, "type.") {
- if f.Sections[s.Section].Type == elf.SHT_PROGBITS {
+ if s.Section != elf.SHN_UNDEF {
+ // Set .File for the library that actually defines the symbol.
+ lsym.File = libpath
+ // The decodetype_* functions in decodetype.go need access to
+ // the type data.
+ if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
lsym.P = readelfsymboldata(f, &s)
}
- if !strings.HasPrefix(lsym.Name, "type..") {
- types = append(types, lsym)
- }
- }
- }
-
- for _, t := range types {
- if decodetype_noptr(t) != 0 || decodetype_usegcprog(t) != 0 {
- continue
- }
- addr := decodetype_gcprog_shlib(t)
- 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
Ctxt.Etextp = last
}
- Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps})
+ Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
}
func mywhatsys() {