• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 syzkaller project authors. All rights reserved.
2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3
4package symbolizer
5
6import (
7	"bufio"
8	"bytes"
9	"strconv"
10
11	"github.com/google/syzkaller/pkg/osutil"
12)
13
14type Symbol struct {
15	Addr uint64
16	Size int
17}
18
19// ReadSymbols returns list of text symbols in the binary bin.
20func ReadSymbols(bin string) (map[string][]Symbol, error) {
21	cmd := osutil.Command("nm", "-nS", bin)
22	stdout, err := cmd.StdoutPipe()
23	if err != nil {
24		return nil, err
25	}
26	defer stdout.Close()
27	if err := cmd.Start(); err != nil {
28		return nil, err
29	}
30	defer cmd.Wait()
31	symbols := make(map[string][]Symbol)
32	s := bufio.NewScanner(stdout)
33	text := [][]byte{[]byte(" t "), []byte(" T ")}
34	for s.Scan() {
35		// A line looks as: "ffffffff8104db90 0000000000000059 t snb_uncore_msr_enable_box"
36		ln := s.Bytes()
37		if !bytes.Contains(ln, text[0]) && !bytes.Contains(ln, text[1]) {
38			continue
39		}
40		sp1 := bytes.IndexByte(ln, ' ')
41		if sp1 == -1 {
42			continue
43		}
44		sp2 := bytes.IndexByte(ln[sp1+1:], ' ')
45		if sp2 == -1 {
46			continue
47		}
48		sp2 += sp1 + 1
49		if !bytes.HasPrefix(ln[sp2:], text[0]) && !bytes.HasPrefix(ln[sp2:], text[1]) {
50			continue
51		}
52		addr, err := strconv.ParseUint(string(ln[:sp1]), 16, 64)
53		if err != nil {
54			continue
55		}
56		size, err := strconv.ParseUint(string(ln[sp1+1:sp2]), 16, 64)
57		if err != nil {
58			continue
59		}
60		name := string(ln[sp2+len(text[0]):])
61		// Note: sizes reported by kernel do not match nm.
62		// Kernel probably subtracts address of this symbol from address of the next symbol.
63		// We could do the same, but for now we just round up size to 16.
64		symbols[name] = append(symbols[name], Symbol{addr, int(size+15) / 16 * 16})
65	}
66	if err := s.Err(); err != nil {
67		return nil, err
68	}
69	return symbols, nil
70}
71