-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathelf.go
124 lines (106 loc) · 2 KB
/
elf.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package nstcc
import (
"debug/elf"
)
func appendELFSym64(b []byte, s elf.Sym64) []byte {
b = appendU32LE(b, s.Name)
b = append(b, s.Info)
b = append(b, s.Other)
b = appendU16LE(b, s.Shndx)
b = appendU64LE(b, s.Value)
b = appendU64LE(b, s.Size)
return b
}
func appendU16LE(b []byte, u uint16) []byte {
return append(b,
uint8(u>>0),
uint8(u>>8),
)
}
func appendU32LE(b []byte, u uint32) []byte {
return append(b,
uint8(u>>0),
uint8(u>>8),
uint8(u>>16),
uint8(u>>24),
)
}
func appendU64LE(b []byte, u uint64) []byte {
return append(b,
uint8(u>>0),
uint8(u>>8),
uint8(u>>16),
uint8(u>>24),
uint8(u>>32),
uint8(u>>40),
uint8(u>>48),
uint8(u>>56),
)
}
func putU32LE(b []byte, u uint32) {
b[0] = uint8(u >> 0)
b[1] = uint8(u >> 8)
b[2] = uint8(u >> 16)
b[3] = uint8(u >> 24)
}
func elfHash(b []byte) (h uint32) {
for _, c := range b {
h = (h << 4) + uint32(c)
g := h & 0xf0000000
if g != 0 {
h ^= g >> 24
}
h &^= g
}
return h
}
type section struct {
data []byte
shName int32
shNum int32
shType int32
shFlags uint32
shInfo int32
shAddrAlign int32
shEntSize int32
shSize uint32
shAddr uint64
shOffset uint32
nbHashedSyms int32
link *section
reloc *section
hash *section
next *section
name []byte
}
func (s *section) putELFStr(sym []byte) int {
ret := len(s.data)
s.data = append(s.data, sym...)
s.data = append(s.data, 0)
return ret
}
func (s *section) putELFSym(arch Arch, value uint64, size uint64, info uint8, other uint8, shndx uint16, name []byte) int {
ret := len(s.data)
nameOffset := 0
switch arch {
case ArchAMD64:
nameOffset = len(s.data)
s.data = appendELFSym64(s.data, elf.Sym64{
Name: 0, // Placeholder.
Info: info,
Other: other,
Shndx: shndx,
Value: value,
Size: size,
})
default:
panic("TODO: implement this architecture")
}
if name != nil {
putU32LE(s.data[nameOffset:], uint32(s.putELFStr(name)))
}
if hs := s.hash; hs != nil {
// TODO.
}
return ret
}