Exemplo n.º 1
0
func FindFunc(fileName string, pc uint64) (s elf.Symbol, err error) {
	file, err := elf.Open(fileName)
	if err != nil {
		return elf.Symbol{}, err
	}

	symbols, err := file.Symbols()
	if err != nil {
		return elf.Symbol{}, err
	}

	funcSymbols := make(Symbols, 0)
	for _, symbol := range symbols {
		if elf.ST_TYPE(symbol.Info) == elf.STT_FUNC {
			funcSymbols = append(funcSymbols, symbol)
		}
	}
	n := len(funcSymbols)
	if n == 0 {
		return elf.Symbol{}, &ErrNoFunctions{}
	}

	sort.Sort(funcSymbols)
	i := sort.Search(n, func(i int) bool { return funcSymbols[i].Value >= pc })
	if i != 0 || funcSymbols[i].Value <= pc {
		if i == n || (funcSymbols[i].Value != pc && i != 0) {
			i--
		}
		return funcSymbols[i], nil
	}

	return elf.Symbol{}, &ErrFunctionNotFound{}
}
Exemplo n.º 2
0
func ldshlibsyms(shlib string) {
	found := false
	libpath := ""
	for _, libdir := range Ctxt.Libdir {
		libpath = filepath.Join(libdir, shlib)
		if _, err := os.Stat(libpath); err == nil {
			found = true
			break
		}
	}
	if !found {
		Diag("cannot find shared library: %s", shlib)
		return
	}
	for _, processedlib := range Ctxt.Shlibs {
		if processedlib.Path == libpath {
			return
		}
	}
	if Ctxt.Debugvlog > 1 && Ctxt.Bso != nil {
		fmt.Fprintf(Ctxt.Bso, "%5.2f ldshlibsyms: found library with name %s at %s\n", obj.Cputime(), shlib, libpath)
		Ctxt.Bso.Flush()
	}

	f, err := elf.Open(libpath)
	if err != nil {
		Diag("cannot open shared library: %s", libpath)
		return
	}
	defer f.Close()
	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{}
	var hash []byte
	for _, s := range syms {
		if elf.ST_TYPE(s.Info) == elf.STT_NOTYPE || elf.ST_TYPE(s.Info) == elf.STT_SECTION {
			continue
		}
		if s.Section == elf.SHN_UNDEF {
			continue
		}
		if strings.HasPrefix(s.Name, "_") {
			continue
		}
		if strings.HasPrefix(s.Name, "runtime.gcbits.") {
			gcmasks[s.Value] = readelfsymboldata(f, &s)
		}
		if s.Name == "go.link.abihashbytes" {
			hash = readelfsymboldata(f, &s)
		}
		if elf.ST_BIND(s.Info) != elf.STB_GLOBAL {
			continue
		}
		lsym := Linklookup(Ctxt, s.Name, 0)
		if lsym.Type != 0 && lsym.Dupok == 0 {
			Diag(
				"Found duplicate symbol %s reading from %s, first found in %s",
				s.Name, shlib, lsym.File)
		}
		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 {
				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
	// autogenerated type equality/hashing functions) and we don't want to generated
	// pcln table entries for these any more so unstitch them from the Textp linked
	// list.
	var last *LSym

	for s := Ctxt.Textp; s != nil; s = s.Next {
		if s.Type == obj.SDYNIMPORT {
			continue
		}

		if last == nil {
			Ctxt.Textp = s
		} else {
			last.Next = s
		}
		last = s
	}

	if last == nil {
		Ctxt.Textp = nil
		Ctxt.Etextp = nil
	} else {
		last.Next = nil
		Ctxt.Etextp = last
	}

	Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash})
}
Exemplo n.º 3
0
func ldshlibsyms(shlib string) {
	libpath := findshlib(shlib)
	if libpath == "" {
		return
	}
	for _, processedlib := range Ctxt.Shlibs {
		if processedlib.Path == libpath {
			return
		}
	}
	if Ctxt.Debugvlog > 1 && Ctxt.Bso != nil {
		fmt.Fprintf(Ctxt.Bso, "%5.2f ldshlibsyms: found library with name %s at %s\n", obj.Cputime(), shlib, libpath)
		Ctxt.Bso.Flush()
	}

	f, err := elf.Open(libpath)
	if err != nil {
		Diag("cannot open shared library: %s", libpath)
		return
	}

	hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
	if err != nil {
		Diag("cannot read ABI hash from shared library %s: %v", libpath, err)
		return
	}

	depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
	if err != nil {
		Diag("cannot read dep list from shared library %s: %v", libpath, err)
		return
	}
	deps := strings.Split(string(depsbytes), "\n")

	syms, err := f.DynamicSymbols()
	if err != nil {
		Diag("cannot read symbols from shared library: %s", libpath)
		return
	}
	for _, elfsym := range syms {
		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
			continue
		}
		lsym := Linklookup(Ctxt, elfsym.Name, 0)
		if lsym.Type != 0 && lsym.Type != obj.SDYNIMPORT && lsym.Dupok == 0 {
			if (lsym.Type != obj.SBSS && lsym.Type != obj.SNOPTRBSS) || len(lsym.R) != 0 || len(lsym.P) != 0 || f.Sections[elfsym.Section].Type != elf.SHT_NOBITS {
				Diag("Found duplicate symbol %s reading from %s, first found in %s", elfsym.Name, shlib, lsym.File)
			}
			if lsym.Size > int64(elfsym.Size) {
				// If the existing symbol is a BSS value that is
				// larger than the one read from the shared library,
				// keep references to that.  Conversely, if the
				// version from the shared libray is larger, we want
				// to make all references be to that.
				continue
			}
		}
		lsym.Type = obj.SDYNIMPORT
		lsym.ElfType = elf.ST_TYPE(elfsym.Info)
		lsym.Size = int64(elfsym.Size)
		if elfsym.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, &elfsym)
			}
		}
	}

	// We might have overwritten some functions above (this tends to happen for the
	// autogenerated type equality/hashing functions) and we don't want to generated
	// pcln table entries for these any more so unstitch them from the Textp linked
	// list.
	var last *LSym

	for s := Ctxt.Textp; s != nil; s = s.Next {
		if s.Type == obj.SDYNIMPORT {
			continue
		}

		if last == nil {
			Ctxt.Textp = s
		} else {
			last.Next = s
		}
		last = s
	}

	if last == nil {
		Ctxt.Textp = nil
		Ctxt.Etextp = nil
	} else {
		last.Next = nil
		Ctxt.Etextp = last
	}

	Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
}
Exemplo n.º 4
0
func ldshlibsyms(shlib string) {
	found := false
	libpath := ""
	for _, libdir := range Ctxt.Libdir {
		libpath = filepath.Join(libdir, shlib)
		if _, err := os.Stat(libpath); err == nil {
			found = true
			break
		}
	}
	if !found {
		Diag("cannot find shared library: %s", shlib)
		return
	}
	for _, processedname := range Ctxt.Shlibs {
		if processedname == libpath {
			return
		}
	}
	if Ctxt.Debugvlog > 1 && Ctxt.Bso != nil {
		fmt.Fprintf(Ctxt.Bso, "%5.2f ldshlibsyms: found library with name %s at %s\n", obj.Cputime(), shlib, libpath)
		Bflush(Ctxt.Bso)
	}

	f, err := elf.Open(libpath)
	if err != nil {
		Diag("cannot open shared library: %s", libpath)
		return
	}
	defer f.Close()
	syms, err := f.DynamicSymbols()
	if err != nil {
		Diag("cannot read symbols from shared library: %s", libpath)
		return
	}
	for _, s := range syms {
		if elf.ST_TYPE(s.Info) == elf.STT_NOTYPE || elf.ST_TYPE(s.Info) == elf.STT_SECTION {
			continue
		}
		if s.Section == elf.SHN_UNDEF {
			continue
		}
		if strings.HasPrefix(s.Name, "_") {
			continue
		}
		lsym := Linklookup(Ctxt, s.Name, 0)
		if lsym.Type != 0 && lsym.Dupok == 0 {
			Diag(
				"Found duplicate symbol %s reading from %s, first found in %s",
				s.Name, shlib, lsym.File)
		}
		lsym.Type = SDYNIMPORT
		lsym.File = libpath
	}

	// We might have overwritten some functions above (this tends to happen for the
	// autogenerated type equality/hashing functions) and we don't want to generated
	// pcln table entries for these any more so unstitch them from the Textp linked
	// list.
	var last *LSym

	for s := Ctxt.Textp; s != nil; s = s.Next {
		if s.Type == SDYNIMPORT {
			continue
		}

		if last == nil {
			Ctxt.Textp = s
		} else {
			last.Next = s
		}
		last = s
	}

	if last == nil {
		Ctxt.Textp = nil
		Ctxt.Etextp = nil
	} else {
		last.Next = nil
		Ctxt.Etextp = last
	}

	Ctxt.Shlibs = append(Ctxt.Shlibs, libpath)
}