Пример #1
0
// The shared library contains a note containing the ABI hash that is mapped into
// memory and there is a local symbol called go.link.abihashbytes that points 16
// bytes into it.
func testABIHashNote(t *testing.T, f *elf.File, note *note) {
	if note.section.Flags != elf.SHF_ALLOC {
		t.Errorf("abi hash section has flags %v", note.section.Flags)
	}
	if !isOffsetLoaded(f, note.section.Offset) {
		t.Errorf("abihash section not contained in PT_LOAD segment")
	}
	var hashbytes elf.Symbol
	symbols, err := f.Symbols()
	if err != nil {
		t.Errorf("error reading symbols %v", err)
		return
	}
	for _, sym := range symbols {
		if sym.Name == "go.link.abihashbytes" {
			hashbytes = sym
		}
	}
	if hashbytes.Name == "" {
		t.Errorf("no symbol called go.link.abihashbytes")
		return
	}
	if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL {
		t.Errorf("%s has incorrect binding %v", hashbytes.Name, elf.ST_BIND(hashbytes.Info))
	}
	if f.Sections[hashbytes.Section] != note.section {
		t.Errorf("%s has incorrect section %v", hashbytes.Name, f.Sections[hashbytes.Section].Name)
	}
	if hashbytes.Value-note.section.Addr != 16 {
		t.Errorf("%s has incorrect offset into section %d", hashbytes.Name, hashbytes.Value-note.section.Addr)
	}
}
Пример #2
0
func elfSymbols(f *os.File) (syms []Sym, goarch string) {
	p, err := elf.NewFile(f)
	if err != nil {
		errorf("parsing %s: %v", f.Name(), err)
		return
	}

	elfSyms, err := p.Symbols()
	if err != nil {
		errorf("parsing %s: %v", f.Name(), err)
		return
	}

	switch p.Machine {
	case elf.EM_X86_64:
		goarch = "amd64"
	case elf.EM_386:
		goarch = "386"
	case elf.EM_ARM:
		goarch = "arm"
	}

	for _, s := range elfSyms {
		sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
		switch s.Section {
		case elf.SHN_UNDEF:
			sym.Code = 'U'
		case elf.SHN_COMMON:
			sym.Code = 'B'
		default:
			i := int(s.Section)
			if i < 0 || i >= len(p.Sections) {
				break
			}
			sect := p.Sections[i]
			switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
			case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
				sym.Code = 'T'
			case elf.SHF_ALLOC:
				sym.Code = 'R'
			case elf.SHF_ALLOC | elf.SHF_WRITE:
				sym.Code = 'D'
			}
		}
		if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
			sym.Code += 'a' - 'A'
		}
		syms = append(syms, sym)
	}

	return
}
Пример #3
0
func elfSymbols(f *os.File) []Sym {
	p, err := elf.NewFile(f)
	if err != nil {
		errorf("parsing %s: %v", f.Name(), err)
		return nil
	}

	elfSyms, err := p.Symbols()
	if err != nil {
		errorf("parsing %s: %v", f.Name(), err)
		return nil
	}

	var syms []Sym
	for _, s := range elfSyms {
		sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
		switch s.Section {
		case elf.SHN_UNDEF:
			sym.Code = 'U'
		case elf.SHN_COMMON:
			sym.Code = 'B'
		default:
			i := int(s.Section)
			if i <= 0 || i > len(p.Sections) {
				break
			}
			sect := p.Sections[i-1]
			switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
			case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
				sym.Code = 'T'
			case elf.SHF_ALLOC:
				sym.Code = 'R'
			case elf.SHF_ALLOC | elf.SHF_WRITE:
				sym.Code = 'D'
			}
		}
		if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
			sym.Code += 'a' - 'A'
		}
		syms = append(syms, sym)
	}

	return syms
}
Пример #4
0
Файл: elf.go Проект: sreis/go
func (f *elfFile) symbols() ([]Sym, error) {
	elfSyms, err := f.elf.Symbols()
	if err != nil {
		return nil, err
	}

	var syms []Sym
	for _, s := range elfSyms {
		sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
		switch s.Section {
		case elf.SHN_UNDEF:
			sym.Code = 'U'
		case elf.SHN_COMMON:
			sym.Code = 'B'
		default:
			i := int(s.Section)
			if i < 0 || i >= len(f.elf.Sections) {
				break
			}
			sect := f.elf.Sections[i]
			switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
			case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
				sym.Code = 'T'
			case elf.SHF_ALLOC:
				sym.Code = 'R'
			case elf.SHF_ALLOC | elf.SHF_WRITE:
				sym.Code = 'D'
			}
		}
		if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
			sym.Code += 'a' - 'A'
		}
		syms = append(syms, sym)
	}

	return syms, nil
}
Пример #5
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})
}