1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package symbolizer
import (
"debug/elf"
"fmt"
"github.com/google/syzkaller/sys/targets"
)
type Symbol struct {
Addr uint64
Size int
}
// 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, 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, false)
}
func read(target *targets.Target, bin string, text bool) (map[string][]Symbol, error) {
file, err := elf.Open(bin)
if err != nil {
return nil, fmt.Errorf("failed to open ELF file %v: %v", bin, err)
}
allSymbols, err := file.Symbols()
if err != nil {
return nil, fmt.Errorf("failed to read ELF symbols: %v", err)
}
symbols := make(map[string][]Symbol)
for _, symb := range allSymbols {
if symb.Size == 0 || symb.Section < 0 || int(symb.Section) >= len(file.Sections) {
continue
}
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
}
// 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.
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
}
|