11
"github.com/sirupsen/logrus"
14
type elfPlatform struct {
19
alsoNone bool // also try with data=none,version=0
25
// knownELFPlatformHeaders is a mapping from target platform names and
26
// plausible headers for the binaries built for those platforms. Call
27
// getKnownELFPlatformHeaders() instead of reading this map directly.
28
knownELFPlatformHeaders = make(map[string][][]byte)
29
knownELFPlatformHeadersOnce sync.Once
30
// knownELFPlatforms is a table of target platforms that we built a
31
// trivial program for, and the other fields are filled in based on
32
// what we got when we ran eu-readelf -h against the results.
33
knownELFPlatforms = []elfPlatform{
35
platform: "linux/386",
36
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
37
class: elf.ELFCLASS32,
38
data: elf.ELFDATA2LSB,
43
platform: "linux/amd64",
44
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
45
class: elf.ELFCLASS64,
46
data: elf.ELFDATA2LSB,
48
machine: elf.EM_X86_64,
51
platform: "linux/arm",
52
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
53
class: elf.ELFCLASS32,
54
data: elf.ELFDATA2LSB,
58
platform: "linux/arm64",
59
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
60
class: elf.ELFCLASS64,
61
data: elf.ELFDATA2LSB,
62
machine: elf.EM_AARCH64,
65
platform: "linux/arm64be",
66
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
67
class: elf.ELFCLASS64,
68
data: elf.ELFDATA2MSB,
69
machine: elf.EM_AARCH64,
72
platform: "linux/loong64",
73
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
74
class: elf.ELFCLASS64,
75
data: elf.ELFDATA2LSB,
76
machine: elf.EM_LOONGARCH,
79
platform: "linux/mips",
80
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
81
class: elf.ELFCLASS32,
82
data: elf.ELFDATA2MSB,
84
flags: []uint32{0, 2}, // elf.EF_MIPS_PIC set, or not
87
platform: "linux/mipsle",
88
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
89
class: elf.ELFCLASS32,
90
data: elf.ELFDATA2LSB,
91
machine: elf.EM_MIPS_RS3_LE,
92
flags: []uint32{0, 2}, // elf.EF_MIPS_PIC set, or not
95
platform: "linux/mips64",
96
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
97
class: elf.ELFCLASS64,
98
data: elf.ELFDATA2MSB,
100
flags: []uint32{0, 2}, // elf.EF_MIPS_PIC set, or not
103
platform: "linux/mips64le",
104
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
105
class: elf.ELFCLASS64,
106
data: elf.ELFDATA2LSB,
107
machine: elf.EM_MIPS_RS3_LE,
108
flags: []uint32{0, 2}, // elf.EF_MIPS_PIC set, or not
111
platform: "linux/ppc",
112
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
113
class: elf.ELFCLASS32,
114
data: elf.ELFDATA2MSB,
118
platform: "linux/ppc64",
119
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
120
class: elf.ELFCLASS64,
121
data: elf.ELFDATA2MSB,
122
machine: elf.EM_PPC64,
125
platform: "linux/ppc64le",
126
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
127
class: elf.ELFCLASS64,
128
data: elf.ELFDATA2LSB,
129
machine: elf.EM_PPC64,
132
platform: "linux/riscv32",
133
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
134
class: elf.ELFCLASS32,
135
data: elf.ELFDATA2LSB,
136
machine: elf.EM_RISCV,
139
platform: "linux/riscv64",
140
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
141
class: elf.ELFCLASS64,
142
data: elf.ELFDATA2LSB,
143
machine: elf.EM_RISCV,
146
platform: "linux/s390x",
147
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
148
class: elf.ELFCLASS64,
149
data: elf.ELFDATA2MSB,
150
machine: elf.EM_S390,
155
// header generates an approximation of what the initial N bytes of a binary
156
// built for a given target looks like
157
func (e *elfPlatform) header() ([][]byte, error) {
161
osabi = []elf.OSABI{elf.ELFOSABI_NONE}
163
for i := range osabi {
168
for f := range flags {
169
var endian binary.ByteOrder
170
var entrySize, phoffSize, shoffSize int
171
header := make([]byte, 40)
172
copy(header, elf.ELFMAG)
175
entrySize, phoffSize, shoffSize = 2, 2, 2
177
entrySize, phoffSize, shoffSize = 4, 4, 4
180
case elf.ELFDATA2LSB:
181
endian = binary.LittleEndian
182
case elf.ELFDATA2MSB:
183
endian = binary.BigEndian
185
return nil, fmt.Errorf("internal error in entry for %q", e.platform)
187
header[elf.EI_OSABI] = byte(osabi[i])
188
header[elf.EI_CLASS] = byte(e.class)
189
header[elf.EI_DATA] = byte(e.data)
190
header[elf.EI_VERSION] = byte(elf.EV_CURRENT)
191
header[elf.EI_ABIVERSION] = 0
192
endian.PutUint16(header[16:], uint16(elf.ET_EXEC))
193
endian.PutUint16(header[18:], uint16(e.machine))
194
endian.PutUint32(header[20:], uint32(elf.EV_CURRENT))
195
endian.PutUint32(header[24+entrySize+phoffSize+shoffSize:], flags[f])
196
headers = append(headers, append([]byte{}, header...))
198
header[elf.EI_DATA] = byte(elf.ELFDATANONE)
199
header[elf.EI_VERSION] = byte(elf.EV_NONE)
200
endian.PutUint32(header[20:], uint32(elf.EV_NONE))
201
headers = append(headers, append([]byte{}, header...))
208
func getKnownELFPlatformHeaders() map[string][][]byte {
209
knownELFPlatformHeadersOnce.Do(func() {
210
for _, p := range knownELFPlatforms {
211
headerList, err := p.header()
213
logrus.Errorf("generating headers for %q: %v\n", p.platform, err)
216
knownELFPlatformHeaders[p.platform] = headerList
219
return knownELFPlatformHeaders