aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/symbolizer
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2022-01-12 13:28:41 +0100
committerAleksandr Nogikh <wp32pw@gmail.com>2022-01-13 17:03:25 +0100
commit24c8419d0db44a0dec71116360d40bd9c82e92b3 (patch)
tree5aa88f38c2507f66f18d5e14377ab0241e8d187b /pkg/symbolizer
parentea7f9ad29297a6f9371422c7b3933185cce0e8d2 (diff)
pkg/symbolizer: switch to debug/elf for symbol extraction
Using debug/elf is better on all fronts: faster, simpler, no external deps.
Diffstat (limited to 'pkg/symbolizer')
-rw-r--r--pkg/symbolizer/nm.go84
1 files changed, 23 insertions, 61 deletions
diff --git a/pkg/symbolizer/nm.go b/pkg/symbolizer/nm.go
index 626d08fd8..109df212b 100644
--- a/pkg/symbolizer/nm.go
+++ b/pkg/symbolizer/nm.go
@@ -4,11 +4,9 @@
package symbolizer
import (
- "bufio"
- "bytes"
- "strconv"
+ "debug/elf"
+ "fmt"
- "github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/sys/targets"
)
@@ -19,80 +17,44 @@ type Symbol struct {
// ReadTextSymbols returns list of text symbols in the binary bin.
func (s *Symbolizer) ReadTextSymbols(bin string) (map[string][]Symbol, error) {
- return read(s.target, bin, "t", "T")
+ return read(s.target, bin, true)
}
// ReadRodataSymbols returns list of rodata symbols in the binary bin.
func (s *Symbolizer) ReadRodataSymbols(bin string) (map[string][]Symbol, error) {
- return read(s.target, bin, "r", "R")
+ return read(s.target, bin, false)
}
-func read(target *targets.Target, bin string, types ...string) (map[string][]Symbol, error) {
- if len(types) != 2 || len(types[0]) != 1 || len(types[1]) != 1 {
- // We assume these things below.
- panic("bad types")
- }
- nm := "nm"
- if target != nil && target.Triple != "" {
- nm = target.Triple + "-" + nm
- }
- cmd := osutil.Command(nm, "-Ptx", bin)
- stdout, err := cmd.StdoutPipe()
+func read(target *targets.Target, bin string, text bool) (map[string][]Symbol, error) {
+ file, err := elf.Open(bin)
if err != nil {
return nil, err
}
- defer stdout.Close()
- if err := cmd.Start(); err != nil {
- return nil, err
+ allSymbols, err := file.Symbols()
+ if err != nil {
+ return nil, fmt.Errorf("failed to read ELF symbols: %v", err)
}
- defer cmd.Wait()
symbols := make(map[string][]Symbol)
- s := bufio.NewScanner(stdout)
- var tt [][]byte
- for _, typ := range types {
- tt = append(tt, []byte(" "+typ+" "))
- }
- for s.Scan() {
- // A line looks as: "snb_uncore_msr_enable_box t ffffffff8104db90 0000000000000059"
- ln := s.Bytes()
- if !bytes.Contains(ln, tt[0]) && !bytes.Contains(ln, tt[1]) {
- continue
- }
-
- sp1 := bytes.IndexByte(ln, ' ')
- if sp1 == -1 {
- continue
- }
- if !bytes.HasPrefix(ln[sp1:], tt[0]) && !bytes.HasPrefix(ln[sp1:], tt[1]) {
- continue
- }
-
- sp2 := sp1 + len(tt[0])
- sp3 := bytes.IndexByte(ln[sp2:], ' ')
- if sp3 == -1 {
- continue
- }
- sp3 += sp2
-
- addr, err := strconv.ParseUint(string(ln[sp2:sp3]), 16, 64)
- if err != nil {
+ for _, symb := range allSymbols {
+ if symb.Size == 0 || symb.Section < 0 || int(symb.Section) >= len(file.Sections) {
continue
}
-
- size, err := strconv.ParseUint(string(ln[sp3+1:]), 16, 64)
- if err != nil || size == 0 {
+ sect := file.Sections[symb.Section]
+ isText := sect.Type == elf.SHT_PROGBITS &&
+ sect.Flags&(elf.SHF_WRITE|elf.SHF_ALLOC|elf.SHF_EXECINSTR) == (elf.SHF_ALLOC|elf.SHF_EXECINSTR)
+ // Note: x86_64 vmlinux .rodata is marked as writable and according to flags it looks like .data,
+ // so we look at the name.
+ if text && !isText || !text && sect.Name != ".rodata" {
continue
}
-
- name := string(ln[:sp1])
-
- // Note: sizes reported by kernel do not match nm.
+ // Note: function sizes reported by kernel do not match symbol tables.
// Kernel probably subtracts address of this symbol from address of the next symbol.
// We could do the same, but for now we just round up size to 16.
- symbols[name] = append(symbols[name], Symbol{addr, int(size+15) / 16 * 16})
- }
- if err := s.Err(); err != nil {
- return nil, err
+ size := int(symb.Size)
+ if text {
+ size = (size + 15) / 16 * 16
+ }
+ symbols[symb.Name] = append(symbols[symb.Name], Symbol{symb.Value, size})
}
return symbols, nil
}