Example #1
0
func newSectionReader(rf io.ReaderAt) (ret sectionReader, err error) {
	ret.macho, err = macho.NewFile(rf)
	if err != nil {
		ret.elf, err = elf.NewFile(rf)
	}
	return
}
Example #2
0
// zipExeReaderElf treats the file as a ELF binary
// (linux/BSD/etc... executable) and attempts to find a zip archive.
func zipExeReaderElf(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	file, err := elf.NewFile(rda)
	if err != nil {
		return nil, err
	}

	var max int64
	for _, sect := range file.Sections {
		if sect.Type == elf.SHT_NOBITS {
			continue
		}

		// Check if this section has a zip file
		if zfile, err := zip.NewReader(sect, int64(sect.Size)); err == nil {
			return zfile, nil
		}

		// Otherwise move end of file pointer
		end := int64(sect.Offset + sect.Size)
		if end > max {
			max = end
		}
	}

	// No zip file within binary, try appended to end
	section := io.NewSectionReader(rda, max, size-max)
	return zip.NewReader(section, section.Size())
}
Example #3
0
func elfexec(b []byte) (uintptr, []KexecSegment, error) {
	f, err := elf.NewFile(bytes.NewReader(b))
	if err != nil {
		return 0, nil, err
	}
	scount := 0
	for _, v := range f.Progs {
		if v.Type.String() == "PT_LOAD" {
			scount++
		}
	}
	if scount > KEXEC_SEGMENT_MAX {
		log.Fatalf("Too many segments: got %v, max is %v", scount, KEXEC_SEGMENT_MAX)
	}
	segs := make([]KexecSegment, scount)
	for i, v := range f.Progs {
		if v.Type.String() == "PT_LOAD" {
			f := v.Open()
			b := pages(uintptr(v.Memsz))
			if _, err := f.Read(b[:v.Filesz]); err != nil {
				log.Fatalf("Reading %d bytes of program header %d: %v", v.Filesz, i, err)
			}
			segs[i] = makeseg(b, uintptr(v.Paddr))
		}
	}
	log.Printf("Using ELF image loader")
	return uintptr(f.Entry), segs, nil
	//return uintptr(0x40000), segs, nil
}
Example #4
0
func TestRun(t *testing.T) {
	file := "samples/simple/O0/strings"
	f := ioReader(file)
	_elf, err := elf.NewFile(f)
	check(wrap(err))
	maps := loader.GetSegments(_elf)
	symbols := loader.GetSymbols(_elf)
	fmt.Println("done loading")
	emulator := MakeBlanketEmulator(maps)
	fmt.Println("done making blanket emulator")

	for rng, symb := range symbols {
		if symb.Type == ds.FUNC && strings.Contains(symb.Name, "str") {
			bbs := extract_bbs(maps, rng)
			if len(bbs) == 0 {
				continue
			}
			fmt.Printf("found function %v\n", symb.Name)
			fmt.Printf("running for %v \n", bbs)
			err := emulator.FullBlanket(bbs)
			if err != nil {
				log.WithFields(log.Fields{"error": err}).Fatal("Error running Blanket")
			}
			ev := emulator.Config.EventHandler.(*be.EventsToMinHash)
			fmt.Println("hash %v", ev.GetHash(60))
			//			fmt.Println("events %v", ev.Inspect())
		}
	}
}
Example #5
0
func Fuzz(data []byte) int {
	f, err := elf.NewFile(bytes.NewReader(data))
	if err != nil {
		if f != nil {
			panic("file is not nil on error")
		}
		return 0
	}
	defer f.Close()
	f.DynamicSymbols()
	f.ImportedLibraries()
	f.ImportedSymbols()
	f.Section(".data")
	f.SectionByType(elf.SHT_GNU_VERSYM)
	f.Symbols()
	dw, err := f.DWARF()
	if err != nil {
		if dw != nil {
			panic("dwarf is not nil on error")
		}
		return 1
	}
	dr := dw.Reader()
	for {
		e, _ := dr.Next()
		if e == nil {
			break
		}
	}
	return 2
}
Example #6
0
func process(file *os.File, name string) error {

	if f, err := elf.NewFile(file); err != nil {
		return err
	} else {
		if fl, err := f.ImportedLibraries(); err != nil {
			return err
		} else {
			if s := f.Section(".interp"); s == nil {
				return errors.New("No interpreter")
			} else {
				if interp, err := s.Data(); err != nil {
					return err
				} else {
					// We could just append the interp but people
					// expect to see that first.
					fl = append([]string{string(interp)}, fl...)
					for _, i := range fl {
						list[i] = true
					}
				}

			}
		}
	}
	return nil
}
Example #7
0
// NewReader returns a reader for the export data section of an object
// (.o) or archive (.a) file read from r.
func NewReader(r io.Reader) (io.Reader, error) {
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, err
	}

	// If the file is an archive, extract the first section.
	const archiveMagic = "!<arch>\n"
	if bytes.HasPrefix(data, []byte(archiveMagic)) {
		section, err := firstSection(data[len(archiveMagic):])
		if err != nil {
			return nil, err
		}
		data = section
	}

	// Data contains an ELF file with a .go_export section.
	// ELF magic number is "\x7fELF".
	ef, err := elf.NewFile(bytes.NewReader(data))
	if err != nil {
		return nil, err
	}
	sec := ef.Section(".go_export")
	if sec == nil {
		return nil, fmt.Errorf("no .go_export section")
	}
	return sec.Open(), nil
}
Example #8
0
func Soname(data []byte) (so string, ok bool) {
	e, err := elf.NewFile(bytes.NewReader(data))
	if err != nil {
		return so, false
	}
	section := e.Section(".dynamic")
	if section == nil {
		// not a dynamic binary.
		return so, false
	}
	// e.stringtable(section.Link)
	dynstr, _ := e.Sections[section.Link].Data()

	switch e.Class {
	case elf.ELFCLASS64:
		n := section.Size / 16 // 2*sizeof(uintptr)
		values := make([]elf.Dyn64, n)
		binary.Read(section.Open(), binary.LittleEndian, values)
		for _, v := range values {
			if elf.DynTag(v.Tag) == elf.DT_SONAME {
				return getstring(dynstr, int(v.Val)), true
			}
		}
	case elf.ELFCLASS32:
		n := section.Size / 8
		values := make([]elf.Dyn32, n)
		binary.Read(section.Open(), binary.LittleEndian, values)
		for _, v := range values {
			if elf.DynTag(v.Tag) == elf.DT_SONAME {
				return getstring(dynstr, int(v.Val)), true
			}
		}
	}
	return "", false
}
Example #9
0
File: elf.go Project: sreis/go
func openElf(r *os.File) (rawFile, error) {
	f, err := elf.NewFile(r)
	if err != nil {
		return nil, err
	}
	return &elfFile{f}, nil
}
Example #10
0
File: main.go Project: ebfe/gover
func openBinary(name string) (Binary, error) {
	f, err := os.Open(name)
	if err != nil {
		return nil, err
	}
	magic := make([]byte, 4)
	if _, err := f.ReadAt(magic[:], 0); err != nil {
		return nil, err
	}

	if bytes.HasPrefix(magic, []byte{0x7f, 'E', 'L', 'F'}) {
		e, err := elf.NewFile(f)
		if err != nil {
			return nil, err
		}
		return &elfBinary{File: e}, nil
	} else if bytes.HasPrefix(magic, []byte{'M', 'Z'}) {
		p, err := pe.Open(name)
		if err != nil {
			return nil, err
		}
		return &peBinary{File: p}, nil
	} else if bytes.HasPrefix(magic, []byte{0xcf, 0xfa, 0xed, 0xfe}) {
		m, err := macho.Open(name)
		if err != nil {
			return nil, err
		}
		return &machoBinary{File: m}, nil
	}
	return nil, fmt.Errorf("unsupported binary format")
}
Example #11
0
func openDebugFile(r io.ReaderAt) (debugFile, error) {
	f, err := elf.NewFile(r)
	if err != nil {
		return nil, err
	}
	return &file{f}, nil
}
Example #12
0
func NewElfLoader(r io.ReaderAt, arch string) (models.Loader, error) {
	file, err := elf.NewFile(r)
	if err != nil {
		return nil, err
	}
	var bits int
	switch file.Class {
	case elf.ELFCLASS32:
		bits = 32
	case elf.ELFCLASS64:
		bits = 64
	default:
		return nil, errors.New("Unknown ELF class.")
	}
	machineName, ok := machineMap[file.Machine]
	if !ok {
		return nil, fmt.Errorf("Unsupported machine: %s", file.Machine)
	}
	return &ElfLoader{
		LoaderHeader: LoaderHeader{
			arch:      machineName,
			bits:      bits,
			os:        "linux",
			entry:     file.Entry,
			byteOrder: file.ByteOrder,
		},
		file: file,
	}, nil
}
Example #13
0
File: elf.go Project: eqv/indika
func Run(file string) {
	f := ioReader(file)
	_elf, err := elf.NewFile(f)
	check(err)
	maps := GetSegments(_elf)
	_ = GetSymbols(_elf)
	fmt.Printf("%v\n", maps)
}
Example #14
0
// Opens the export data file at the given path. If this is an ELF file,
// searches for and opens the .go_export section. If this is an archive,
// reads the export data from the first member, which is assumed to be an ELF file.
// This is intended to replicate the logic in gofrontend.
func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
	f, err := os.Open(fpath)
	if err != nil {
		return
	}
	closer = f
	defer func() {
		if err != nil && closer != nil {
			f.Close()
		}
	}()

	var magic [4]byte
	_, err = f.ReadAt(magic[:], 0)
	if err != nil {
		return
	}

	var elfreader io.ReaderAt
	switch string(magic[:]) {
	case gccgov1Magic, goimporterMagic:
		// Raw export data.
		reader = f
		return

	case archiveMagic:
		// TODO(pcc): Read the archive directly instead of using "ar".
		f.Close()
		closer = nil

		cmd := exec.Command("ar", "p", fpath)
		var out []byte
		out, err = cmd.Output()
		if err != nil {
			return
		}

		elfreader = bytes.NewReader(out)

	default:
		elfreader = f
	}

	ef, err := elf.NewFile(elfreader)
	if err != nil {
		return
	}

	sec := ef.Section(".go_export")
	if sec == nil {
		err = fmt.Errorf("%s: .go_export section not found", fpath)
		return
	}

	reader = sec.Open()
	return
}
Example #15
0
func loadTables(f *os.File) (textStart uint64, symtab, pclntab []byte, err error) {
	if obj, err := elf.NewFile(f); err == nil {
		if sect := obj.Section(".text"); sect != nil {
			textStart = sect.Addr
		}
		if sect := obj.Section(".gosymtab"); sect != nil {
			if symtab, err = sect.Data(); err != nil {
				return 0, nil, nil, err
			}
		}
		if sect := obj.Section(".gopclntab"); sect != nil {
			if pclntab, err = sect.Data(); err != nil {
				return 0, nil, nil, err
			}
		}
		return textStart, symtab, pclntab, nil
	}

	if obj, err := macho.NewFile(f); err == nil {
		if sect := obj.Section("__text"); sect != nil {
			textStart = sect.Addr
		}
		if sect := obj.Section("__gosymtab"); sect != nil {
			if symtab, err = sect.Data(); err != nil {
				return 0, nil, nil, err
			}
		}
		if sect := obj.Section("__gopclntab"); sect != nil {
			if pclntab, err = sect.Data(); err != nil {
				return 0, nil, nil, err
			}
		}
		return textStart, symtab, pclntab, nil
	}

	if obj, err := pe.NewFile(f); err == nil {
		if sect := obj.Section(".text"); sect != nil {
			textStart = uint64(sect.VirtualAddress)
		}
		if sect := obj.Section(".gosymtab"); sect != nil {
			if symtab, err = sect.Data(); err != nil {
				return 0, nil, nil, err
			}
		}
		if sect := obj.Section(".gopclntab"); sect != nil {
			if pclntab, err = sect.Data(); err != nil {
				return 0, nil, nil, err
			}
		}
		return textStart, symtab, pclntab, nil
	}

	return 0, nil, nil, fmt.Errorf("unrecognized binary format")
}
Example #16
0
File: elf.go Project: h8liu/golang
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
}
Example #17
0
func main() {
	fd, err := os.Open("/bin/bash")
	argh(err)
	bash, err := elf.NewFile(fd)
	argh(err)
	section := bash.Section(".note.gnu.build-id")
	if section == nil {
		panic("No note")
	}
	bytes, err := section.Data()
	argh(err)
	fmt.Printf("%x\n", bytes[len(bytes)-buildIdLen:])
}
Example #18
0
File: main.go Project: jteso/alone
func isStatic(r io.ReaderAt) (bool, error) {
	f, err := elf.NewFile(r)
	if err != nil {
		return false, err
	}
	libs, err := f.ImportedLibraries()
	if err != nil {
		return false, err
	}
	if len(libs) > 0 {
		return false, nil
	}
	return true, nil
}
Example #19
0
func NewFile(r io.ReaderAt) (binaryx.File, error) {
	elfBinary, err := elf.NewFile(r)
	if err == nil {
		return newFile(&elfx.File{elfBinary})
	}
	machoBinary, err := macho.NewFile(r)
	if err == nil {
		return newFile(&machox.File{machoBinary})
	}
	peBinary, err := pe.NewFile(r)
	if err == nil {
		return newFile(&pex.File{peBinary})
	}
	return nil, err
}
Example #20
0
// GetBuildID returns the GNU build-ID for an ELF binary.
//
// If no build-ID was found but the binary was read without error, it returns
// (nil, nil).
func GetBuildID(binary io.ReaderAt) ([]byte, error) {
	f, err := elf.NewFile(binary)
	if err != nil {
		return nil, err
	}

	findBuildID := func(notes []elfNote) ([]byte, error) {
		var buildID []byte
		for _, note := range notes {
			if note.Name == "GNU" && note.Type == noteTypeGNUBuildID {
				if buildID == nil {
					buildID = note.Desc
				} else {
					return nil, fmt.Errorf("multiple build ids found, don't know which to use!")
				}
			}
		}
		return buildID, nil
	}

	for _, p := range f.Progs {
		if p.Type != elf.PT_NOTE {
			continue
		}
		notes, err := parseNotes(p.Open(), int(p.Align), f.ByteOrder)
		if err != nil {
			return nil, err
		}
		if b, err := findBuildID(notes); b != nil || err != nil {
			return b, err
		}
	}
	for _, s := range f.Sections {
		if s.Type != elf.SHT_NOTE {
			continue
		}
		notes, err := parseNotes(s.Open(), int(s.Addralign), f.ByteOrder)
		if err != nil {
			return nil, err
		}
		if b, err := findBuildID(notes); b != nil || err != nil {
			return b, err
		}
	}
	return nil, nil
}
Example #21
0
func grabDebugLineSection(p string, t *testing.T) []byte {
	f, err := os.Open(p)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	ef, err := elf.NewFile(f)
	if err == nil {
		data, _ := ef.Section(".debug_line").Data()
		return data
	}

	mf, _ := macho.NewFile(f)
	data, _ := mf.Section("__debug_line").Data()

	return data
}
Example #22
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
}
Example #23
0
func (dbp *Process) findExecutable(path string) (*elf.File, error) {
	if path == "" {
		path = fmt.Sprintf("/proc/%d/exe", dbp.Pid)
	}
	f, err := os.OpenFile(path, 0, os.ModePerm)
	if err != nil {
		return nil, err
	}
	elfFile, err := elf.NewFile(f)
	if err != nil {
		return nil, err
	}
	data, err := elfFile.DWARF()
	if err != nil {
		return nil, err
	}
	dbp.dwarf = data
	return elfFile, nil
}
Example #24
0
File: note.go Project: pjump/gcc
// readELFGoBuildID the Go build ID string from an ELF binary.
// The Go build ID is stored in a note described by an ELF PT_NOTE prog header.
// The caller has already opened filename, to get f, and read the first 4 kB out, in data.
func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string, err error) {
	// Assume the note content is in the first 4 kB, already read.
	// Rewrite the ELF header to set shnum to 0, so that we can pass
	// the data to elf.NewFile and it will decode the Prog list but not
	// try to read the section headers and the string table from disk.
	// That's a waste of I/O when all we care about is the Prog list
	// and the one ELF note.
	switch elf.Class(data[elf.EI_CLASS]) {
	case elf.ELFCLASS32:
		data[48] = 0
		data[49] = 0
	case elf.ELFCLASS64:
		data[60] = 0
		data[61] = 0
	}

	const elfGoBuildIDTag = 4

	ef, err := elf.NewFile(bytes.NewReader(data))
	if err != nil {
		return "", &os.PathError{Path: filename, Op: "parse", Err: err}
	}
	for _, p := range ef.Progs {
		if p.Type != elf.PT_NOTE || p.Off >= uint64(len(data)) || p.Off+p.Filesz >= uint64(len(data)) || p.Filesz < 16 {
			continue
		}

		note := data[p.Off : p.Off+p.Filesz]
		nameSize := ef.ByteOrder.Uint32(note)
		valSize := ef.ByteOrder.Uint32(note[4:])
		tag := ef.ByteOrder.Uint32(note[8:])
		name := note[12:16]
		if nameSize != 4 || 16+valSize > uint32(len(note)) || tag != elfGoBuildIDTag || !bytes.Equal(name, elfGoNote) {
			continue
		}

		return string(note[16 : 16+valSize]), nil
	}

	// No note. Treat as successful but build ID empty.
	return "", nil
}
Example #25
0
File: hasher.go Project: eqv/indika
func main() {
	file := os.Args[1]

	log.SetLevel(log.ErrorLevel)

	fmt.Printf("%v\n", os.Args)

	if len(os.Args) >= 3 && os.Args[2] == "d" {
		log.SetLevel(log.DebugLevel)
	}

	f := ioReader(file)
	_elf, err := elf.NewFile(f)
	check(wrap(err))
	maps := loader.GetSegments(_elf)
	symbols := loader.GetSymbols(_elf)

	fmt.Println("done loading")
	fmt.Printf("maps %v\n", maps)

	for rng, symb := range symbols {
		if !are_we_interessted_in_this(symb) {
			continue
		}
		bbs := extract_bbs(maps, rng)
		if len(bbs) == 0 {
			continue
		}
		fmt.Printf("%v : ", pad_func_name(symb.Name))
		emulator := MakeBlanketEmulator(maps)
		err := emulator.FullBlanket(bbs)
		if err != nil {
			log.WithFields(log.Fields{"error": err}).Error("Error running Blanket")
			continue
		}
		ev := emulator.Events
		fmt.Printf("hash %v\n", hex.EncodeToString(ev.GetHash(32)))
		log.WithFields(log.Fields{"events": ev.Inspect()}).Debug("Done running Blanket")
		emulator.Close()
		emulator = nil
	}
}
Example #26
0
func FixFile(filename string) error {
	fd, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return err
	}
	defer fd.Close()

	elf, err := ELF.NewFile(fd)
	if err != nil {
		log.Print("Failed to parse ELF. This can happen if the binary is already packed.")
		return err
	}
	defer elf.Close()

	log.Printf("%+v", elf.FileHeader)
	err = fixelf(elf, fd)
	if err != nil {
		log.Fatal("Failure to read ELF header")
		return err
	}
	return nil
}
Example #27
0
func main() {

	// cat <bin> | ./a.out
	if len(os.Args) == 1 {

		var buf bytes.Buffer
		if _, err := io.Copy(&buf, os.Stdin); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		data := buf.Bytes()
		if len(data) > 0 {
			file, e := elf.NewFile(bytes.NewReader(data))
			if e != nil {
				fmt.Println(INVALID)
				os.Exit(1)
			}
			checksec(file)
		}

		// FILE [FILE]*
	} else {

		for _, arg := range os.Args[1:] {

			file, e := elf.Open(arg)
			if e != nil {
				fmt.Printf("%s,%s\n", arg, INVALID)

			} else {
				fmt.Print(arg, SEP)
				checksec(file)
				file.Close()
			}
		}
	}
}
Example #28
0
// This function is an exact copy of gccgoimporter.openExportFile.
func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
	f, err := os.Open(fpath)
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			f.Close()
		}
	}()
	closer = f

	var magic [4]byte
	_, err = f.ReadAt(magic[:], 0)
	if err != nil {
		return
	}

	if string(magic[:]) == "v1;\n" {
		// Raw export data.
		reader = f
		return
	}

	ef, err := elf.NewFile(f)
	if err != nil {
		return
	}

	sec := ef.Section(".go_export")
	if sec == nil {
		err = fmt.Errorf("%s: .go_export section not found", fpath)
		return
	}

	reader = sec.Open()
	return
}
Example #29
0
func Depends(data []byte) (needed []string, err error) {
	e, err := elf.NewFile(bytes.NewReader(data))
	if err != nil {
		return nil, err
	}
	section := e.Section(".dynamic")
	if section == nil {
		// not a dynamic binary.
		return nil, nil
	}
	// e.stringtable(section.Link)
	dynstr, _ := e.Sections[section.Link].Data()

	switch e.Class {
	case elf.ELFCLASS64:
		n := section.Size / 16 // 2*sizeof(uintptr)
		values := make([]elf.Dyn64, n)
		binary.Read(section.Open(), binary.LittleEndian, values)
		for _, v := range values {
			if elf.DynTag(v.Tag) == elf.DT_NEEDED {
				so := getstring(dynstr, int(v.Val))
				needed = append(needed, so)
			}
		}
	case elf.ELFCLASS32:
		n := section.Size / 8
		values := make([]elf.Dyn32, n)
		binary.Read(section.Open(), binary.LittleEndian, values)
		for _, v := range values {
			if elf.DynTag(v.Tag) == elf.DT_NEEDED {
				so := getstring(dynstr, int(v.Val))
				needed = append(needed, so)
			}
		}
	}
	return needed, nil
}
Example #30
0
func findAddr(r io.ReaderAt, sym string) (uintptr, error) {
	file, err := elf.NewFile(r)
	if err != nil {
		return 0, err
	}
	defer file.Close()

	var (
		textStart       uint64
		symtab, pclntab []byte
	)

	if sect := file.Section(".text"); sect != nil {
		textStart = sect.Addr
	}
	if sect := file.Section(".gosymtab"); sect != nil {
		if symtab, err = sect.Data(); err != nil {
			return 0, err
		}
	}
	if sect := file.Section(".gopclntab"); sect != nil {
		if pclntab, err = sect.Data(); err != nil {
			return 0, err
		}
	}

	tab, err := gosym.NewTable(symtab, gosym.NewLineTable(pclntab, textStart))
	if err != nil {
		return 0, err
	}

	fn := tab.LookupFunc(sym)
	if fn == nil {
		return 0, fmt.Errorf("could not find symbol %q", sym)
	}
	return uintptr(fn.Entry), nil
}