-
Notifications
You must be signed in to change notification settings - Fork 6
/
gnuver.go
102 lines (91 loc) · 2.28 KB
/
gnuver.go
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Package elf: gnuver.go implements the GNU Version table specification.
package elf
import "errors"
// GNUVersion holds the version information
type GNUVersion struct {
File string
Name string
}
// ImportedSymbol will hold information on external imports.
type ImportedSymbol struct {
Name string
Version string
Library string
}
// ParseGNUVersionTable parses the GNU version tables.
func (p *Parser) ParseGNUVersionTable(str []byte) error {
if p.F.GNUVersion != nil {
return errors.New("already processed GNU version table")
}
vn := p.F.GetSectionByType(SHT_GNU_VERNEED)
if vn == nil {
return errors.New("no gnu verneed section in file")
}
d, _ := vn.Data()
var gnuVer []GNUVersion
i := 0
for {
if i+16 > len(d) {
break
}
vers := p.F.ByteOrder().Uint16(d[i : i+2])
if vers != 1 {
break
}
cnt := p.F.ByteOrder().Uint16(d[i+2 : i+4])
fileoff := p.F.ByteOrder().Uint32(d[i+4 : i+8])
aux := p.F.ByteOrder().Uint32(d[i+8 : i+12])
next := p.F.ByteOrder().Uint32(d[i+12 : i+16])
file, _ := getString(str, int(fileoff))
var name string
j := i + int(aux)
for c := 0; c < int(cnt); c++ {
if j+16 > len(d) {
break
}
other := p.F.ByteOrder().Uint16(d[j+6 : j+8])
nameoff := p.F.ByteOrder().Uint32(d[j+8 : j+12])
next := p.F.ByteOrder().Uint32(d[j+12 : j+16])
name, _ = getString(str, int(nameoff))
ndx := int(other)
if ndx >= len(gnuVer) {
a := make([]GNUVersion, 2*(ndx+1))
copy(a, gnuVer)
gnuVer = a
}
gnuVer[ndx] = GNUVersion{file, name}
if next == 0 {
break
}
j += int(next)
}
if next == 0 {
break
}
i += int(next)
}
// Versym parallels symbol table, indexing into verneed.
vs := p.F.GetSectionByType(SHT_GNU_VERSYM)
if vs == nil {
return errors.New("no gnu versym section in file")
}
d, _ = vs.Data()
p.F.GNUVersion = gnuVer
p.F.GNUVersionSym = d
return nil
}
// gnuVersion adds Library and Version information to namedSymbol,
// which came from offset i of the symbol table.
func (p *Parser) gnuVersion(i int) (string, string) {
// Each entry is two bytes.
i = (i + 1) * 2
if i >= len(p.F.GNUVersionSym) {
return "", ""
}
j := int(p.F.ByteOrder().Uint16(p.F.GNUVersionSym[i:]))
if j < 2 || j >= len(p.F.GNUVersion) {
return "", ""
}
n := &p.F.GNUVersion[j]
return n.File, n.Name
}