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
125
126
127
128
129
130
131
132
|
package main
import (
"encoding/binary"
)
const (
EI_NIDENT = 16
ET_NONE = 0
ET_REL = 1
ET_EXEC = 2
ET_DYN = 3
ET_CORE = 4
MIPS = 0x08
EHSIZE = 52
PHENSIZE = 0x20
SHENTSIZE = 0x28
PT_NULL = 0
PT_LOAD = 1
PT_DYNAMIC = 2
PT_INTERP = 3
PT_NOTE = 4
PT_SHLIB = 5
PT_PHDR = 6
PT_TLS = 7
PF_READ = 4
PF_WRITE = 2
PF_EXEC = 1
)
type ElfHeader struct {
e_ident [EI_NIDENT]byte
e_type uint16
e_machine uint16
e_version uint32
e_entry uint32
e_phoff uint32
e_shoff uint32
e_flags uint32
e_ehsize uint16
e_phentsize uint16
e_phnum uint16
e_shentsize uint16
e_shnum uint16
e_shstrndx uint16
}
type ProgramHeader struct {
ptype uint32
offset uint32
vaddr uint32
paddr uint32
filesz uint32
memsz uint32
flags uint32
align uint32
}
func EHInit(e_entry uint32, e_phnum uint16) ElfHeader {
var e ElfHeader
e.e_ident = [EI_NIDENT]byte{0x7f, 0x45, 0x4c, 0x46, // ELF magic number
0x01, // 32-bit format
0x00, // Endian
0x01, // ELF Version
0x00, // Target OS
0x00, // Target ABI
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // Padding
if byteOrder == binary.BigEndian {
e.e_ident[5] = 0x02
} else {
e.e_ident[5] = 0x01
}
e.e_type = ET_EXEC
e.e_machine = MIPS
e.e_version = 0x01
e.e_entry = e_entry
e.e_phoff = EHSIZE // Program headers will be after ELF Header
e.e_shoff = 0
e.e_ehsize = EHSIZE
e.e_phentsize = PHENSIZE
e.e_phnum = e_phnum
e.e_shentsize = SHENTSIZE
e.e_shnum = 0
e.e_shstrndx = 0
return e
}
/* NOTES: On the ToBytes methods
* I understand that these two methods are not the prettiest, but I need
* something to convert these structs to to byte arrays. From what I've read so
* far there seems to be no way to do this. It appears that encoding/gob
* ignores the size of data types, which is needed, and json serialization
* would not produce the proper output.
*/
func (e *ElfHeader) ToBytes() []byte {
bytes := make([]byte, EHSIZE)
i := 0
for _, b := range e.e_ident {
bytes[i] = b
i++
}
byteOrder.PutUint16(bytes[EI_NIDENT:], e.e_type)
byteOrder.PutUint16(bytes[18:], e.e_machine)
byteOrder.PutUint32(bytes[20:], e.e_version)
byteOrder.PutUint32(bytes[24:], e.e_entry)
byteOrder.PutUint32(bytes[28:], e.e_phoff)
byteOrder.PutUint32(bytes[32:], e.e_shoff)
byteOrder.PutUint32(bytes[36:], e.e_flags)
byteOrder.PutUint16(bytes[40:], e.e_ehsize)
byteOrder.PutUint16(bytes[42:], e.e_phentsize)
byteOrder.PutUint16(bytes[44:], e.e_phnum)
byteOrder.PutUint16(bytes[46:], e.e_shentsize)
byteOrder.PutUint16(bytes[48:], e.e_shnum)
byteOrder.PutUint16(bytes[50:], e.e_shstrndx)
return bytes
}
func (p *ProgramHeader) ToBytes() []byte {
bytes := make([]byte, PHENSIZE)
byteOrder.PutUint32(bytes[0:], p.ptype)
byteOrder.PutUint32(bytes[4:], p.offset)
byteOrder.PutUint32(bytes[8:], p.vaddr)
byteOrder.PutUint32(bytes[12:], p.paddr)
byteOrder.PutUint32(bytes[16:], p.filesz)
byteOrder.PutUint32(bytes[20:], p.memsz)
byteOrder.PutUint32(bytes[24:], p.flags)
byteOrder.PutUint32(bytes[28:], p.align)
return bytes
}
|