1
2
3
4
5
6
7
8 package macho
9
10 import (
11 "encoding/binary"
12 "strconv"
13 )
14
15
16 type FileHeader struct {
17 Magic uint32
18 Cpu Cpu
19 SubCpu uint32
20 Type HdrType
21 NCommands uint32
22 SizeCommands uint32
23 Flags HdrFlags
24 }
25
26 func (h *FileHeader) Put(b []byte, o binary.ByteOrder) int {
27 o.PutUint32(b[0:], h.Magic)
28 o.PutUint32(b[4:], uint32(h.Cpu))
29 o.PutUint32(b[8:], h.SubCpu)
30 o.PutUint32(b[12:], uint32(h.Type))
31 o.PutUint32(b[16:], h.NCommands)
32 o.PutUint32(b[20:], h.SizeCommands)
33 o.PutUint32(b[24:], uint32(h.Flags))
34 if h.Magic == Magic32 {
35 return 28
36 }
37 o.PutUint32(b[28:], 0)
38 return 32
39 }
40
41 const (
42 fileHeaderSize32 = 7 * 4
43 fileHeaderSize64 = 8 * 4
44 )
45
46 const (
47 Magic32 uint32 = 0xfeedface
48 Magic64 uint32 = 0xfeedfacf
49 MagicFat uint32 = 0xcafebabe
50 )
51
52 type HdrFlags uint32
53 type SegFlags uint32
54 type SecFlags uint32
55
56
57 type HdrType uint32
58
59 const (
60 MhObject HdrType = 1
61 MhExecute HdrType = 2
62 MhCore HdrType = 4
63 MhDylib HdrType = 6
64 MhBundle HdrType = 8
65 MhDsym HdrType = 0xa
66 )
67
68 var typeStrings = []intName{
69 {uint32(MhObject), "Obj"},
70 {uint32(MhExecute), "Exec"},
71 {uint32(MhDylib), "Dylib"},
72 {uint32(MhBundle), "Bundle"},
73 {uint32(MhDsym), "Dsym"},
74 }
75
76 func (t HdrType) String() string { return stringName(uint32(t), typeStrings, false) }
77 func (t HdrType) GoString() string { return stringName(uint32(t), typeStrings, true) }
78
79
80 type Cpu uint32
81
82 const cpuArch64 = 0x01000000
83
84 const (
85 Cpu386 Cpu = 7
86 CpuAmd64 Cpu = Cpu386 | cpuArch64
87 CpuArm Cpu = 12
88 CpuArm64 Cpu = CpuArm | cpuArch64
89 CpuPpc Cpu = 18
90 CpuPpc64 Cpu = CpuPpc | cpuArch64
91 )
92
93 var cpuStrings = []intName{
94 {uint32(Cpu386), "Cpu386"},
95 {uint32(CpuAmd64), "CpuAmd64"},
96 {uint32(CpuArm), "CpuArm"},
97 {uint32(CpuArm64), "CpuArm64"},
98 {uint32(CpuPpc), "CpuPpc"},
99 {uint32(CpuPpc64), "CpuPpc64"},
100 }
101
102 func (i Cpu) String() string { return stringName(uint32(i), cpuStrings, false) }
103 func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }
104
105
106 type LoadCmd uint32
107
108 func (c LoadCmd) Command() LoadCmd { return c }
109
110 const (
111
112 LcSegment LoadCmd = 0x1
113 LcSymtab LoadCmd = 0x2
114 LcThread LoadCmd = 0x4
115 LcUnixthread LoadCmd = 0x5
116 LcDysymtab LoadCmd = 0xb
117 LcDylib LoadCmd = 0xc
118 LcIdDylib LoadCmd = 0xd
119 LcLoadDylinker LoadCmd = 0xe
120 LcIdDylinker LoadCmd = 0xf
121 LcSegment64 LoadCmd = 0x19
122 LcUuid LoadCmd = 0x1b
123 LcCodeSignature LoadCmd = 0x1d
124 LcSegmentSplitInfo LoadCmd = 0x1e
125 LcRpath LoadCmd = 0x8000001c
126 LcEncryptionInfo LoadCmd = 0x21
127 LcDyldInfo LoadCmd = 0x22
128 LcDyldInfoOnly LoadCmd = 0x80000022
129 LcVersionMinMacosx LoadCmd = 0x24
130 LcVersionMinIphoneos LoadCmd = 0x25
131 LcFunctionStarts LoadCmd = 0x26
132 LcDyldEnvironment LoadCmd = 0x27
133 LcMain LoadCmd = 0x80000028
134 LcDataInCode LoadCmd = 0x29
135 LcSourceVersion LoadCmd = 0x2a
136 LcDylibCodeSignDrs LoadCmd = 0x2b
137 LcEncryptionInfo64 LoadCmd = 0x2c
138 LcVersionMinTvos LoadCmd = 0x2f
139 LcVersionMinWatchos LoadCmd = 0x30
140 )
141
142 var cmdStrings = []intName{
143 {uint32(LcSegment), "LoadCmdSegment"},
144 {uint32(LcThread), "LoadCmdThread"},
145 {uint32(LcUnixthread), "LoadCmdUnixThread"},
146 {uint32(LcDylib), "LoadCmdDylib"},
147 {uint32(LcIdDylib), "LoadCmdIdDylib"},
148 {uint32(LcLoadDylinker), "LoadCmdLoadDylinker"},
149 {uint32(LcIdDylinker), "LoadCmdIdDylinker"},
150 {uint32(LcSegment64), "LoadCmdSegment64"},
151 {uint32(LcUuid), "LoadCmdUuid"},
152 {uint32(LcRpath), "LoadCmdRpath"},
153 {uint32(LcDyldEnvironment), "LoadCmdDyldEnv"},
154 {uint32(LcMain), "LoadCmdMain"},
155 {uint32(LcDataInCode), "LoadCmdDataInCode"},
156 {uint32(LcSourceVersion), "LoadCmdSourceVersion"},
157 {uint32(LcDyldInfo), "LoadCmdDyldInfo"},
158 {uint32(LcDyldInfoOnly), "LoadCmdDyldInfoOnly"},
159 {uint32(LcVersionMinMacosx), "LoadCmdMinOsx"},
160 {uint32(LcFunctionStarts), "LoadCmdFunctionStarts"},
161 }
162
163 func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) }
164 func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }
165
166 type (
167
168 Segment32 struct {
169 LoadCmd
170 Len uint32
171 Name [16]byte
172 Addr uint32
173 Memsz uint32
174 Offset uint32
175 Filesz uint32
176 Maxprot uint32
177 Prot uint32
178 Nsect uint32
179 Flag SegFlags
180 }
181
182
183 Segment64 struct {
184 LoadCmd
185 Len uint32
186 Name [16]byte
187 Addr uint64
188 Memsz uint64
189 Offset uint64
190 Filesz uint64
191 Maxprot uint32
192 Prot uint32
193 Nsect uint32
194 Flag SegFlags
195 }
196
197
198 SymtabCmd struct {
199 LoadCmd
200 Len uint32
201 Symoff uint32
202 Nsyms uint32
203 Stroff uint32
204 Strsize uint32
205 }
206
207
208 DysymtabCmd struct {
209 LoadCmd
210 Len uint32
211 Ilocalsym uint32
212 Nlocalsym uint32
213 Iextdefsym uint32
214 Nextdefsym uint32
215 Iundefsym uint32
216 Nundefsym uint32
217 Tocoffset uint32
218 Ntoc uint32
219 Modtaboff uint32
220 Nmodtab uint32
221 Extrefsymoff uint32
222 Nextrefsyms uint32
223 Indirectsymoff uint32
224 Nindirectsyms uint32
225 Extreloff uint32
226 Nextrel uint32
227 Locreloff uint32
228 Nlocrel uint32
229 }
230
231
232 DylibCmd struct {
233 LoadCmd
234 Len uint32
235 Name uint32
236 Time uint32
237 CurrentVersion uint32
238 CompatVersion uint32
239 }
240
241
242 DylinkerCmd struct {
243 LoadCmd
244 Len uint32
245 Name uint32
246 }
247
248
249 RpathCmd struct {
250 LoadCmd
251 Len uint32
252 Path uint32
253 }
254
255
256 Thread struct {
257 LoadCmd
258 Len uint32
259 Type uint32
260 Data []uint32
261 }
262
263
264 DyldInfoCmd struct {
265 LoadCmd
266 Len uint32
267 RebaseOff, RebaseLen uint32
268 BindOff, BindLen uint32
269 WeakBindOff, WeakBindLen uint32
270 LazyBindOff, LazyBindLen uint32
271 ExportOff, ExportLen uint32
272 }
273
274
275 LinkEditDataCmd struct {
276 LoadCmd
277 Len uint32
278 DataOff, DataLen uint32
279 }
280
281
282 EncryptionInfoCmd struct {
283 LoadCmd
284 Len uint32
285 CryptOff, CryptLen uint32
286 CryptId uint32
287 }
288
289 UuidCmd struct {
290 LoadCmd
291 Len uint32
292 Id [16]byte
293 }
294
295
296
297 EntryPointCmd struct {
298 LoadCmd
299 Len uint32
300 EntryOff uint64
301 StackSize uint64
302 }
303
304 NoteCmd struct {
305 LoadCmd
306 Len uint32
307 Name [16]byte
308 Offset, Filesz uint64
309 }
310 )
311
312 const (
313 FlagNoUndefs HdrFlags = 0x1
314 FlagIncrLink HdrFlags = 0x2
315 FlagDyldLink HdrFlags = 0x4
316 FlagBindAtLoad HdrFlags = 0x8
317 FlagPrebound HdrFlags = 0x10
318 FlagSplitSegs HdrFlags = 0x20
319 FlagLazyInit HdrFlags = 0x40
320 FlagTwoLevel HdrFlags = 0x80
321 FlagForceFlat HdrFlags = 0x100
322 FlagNoMultiDefs HdrFlags = 0x200
323 FlagNoFixPrebinding HdrFlags = 0x400
324 FlagPrebindable HdrFlags = 0x800
325 FlagAllModsBound HdrFlags = 0x1000
326 FlagSubsectionsViaSymbols HdrFlags = 0x2000
327 FlagCanonical HdrFlags = 0x4000
328 FlagWeakDefines HdrFlags = 0x8000
329 FlagBindsToWeak HdrFlags = 0x10000
330 FlagAllowStackExecution HdrFlags = 0x20000
331 FlagRootSafe HdrFlags = 0x40000
332 FlagSetuidSafe HdrFlags = 0x80000
333 FlagNoReexportedDylibs HdrFlags = 0x100000
334 FlagPIE HdrFlags = 0x200000
335 FlagDeadStrippableDylib HdrFlags = 0x400000
336 FlagHasTLVDescriptors HdrFlags = 0x800000
337 FlagNoHeapExecution HdrFlags = 0x1000000
338 FlagAppExtensionSafe HdrFlags = 0x2000000
339 )
340
341
342 type Section32 struct {
343 Name [16]byte
344 Seg [16]byte
345 Addr uint32
346 Size uint32
347 Offset uint32
348 Align uint32
349 Reloff uint32
350 Nreloc uint32
351 Flags SecFlags
352 Reserve1 uint32
353 Reserve2 uint32
354 }
355
356
357 type Section64 struct {
358 Name [16]byte
359 Seg [16]byte
360 Addr uint64
361 Size uint64
362 Offset uint32
363 Align uint32
364 Reloff uint32
365 Nreloc uint32
366 Flags SecFlags
367 Reserve1 uint32
368 Reserve2 uint32
369 Reserve3 uint32
370 }
371
372
373 type Nlist32 struct {
374 Name uint32
375 Type uint8
376 Sect uint8
377 Desc uint16
378 Value uint32
379 }
380
381
382 type Nlist64 struct {
383 Name uint32
384 Type uint8
385 Sect uint8
386 Desc uint16
387 Value uint64
388 }
389
390 func (n *Nlist64) Put64(b []byte, o binary.ByteOrder) uint32 {
391 o.PutUint32(b[0:], n.Name)
392 b[4] = byte(n.Type)
393 b[5] = byte(n.Sect)
394 o.PutUint16(b[6:], n.Desc)
395 o.PutUint64(b[8:], n.Value)
396 return 8 + 8
397 }
398
399 func (n *Nlist64) Put32(b []byte, o binary.ByteOrder) uint32 {
400 o.PutUint32(b[0:], n.Name)
401 b[4] = byte(n.Type)
402 b[5] = byte(n.Sect)
403 o.PutUint16(b[6:], n.Desc)
404 o.PutUint32(b[8:], uint32(n.Value))
405 return 8 + 4
406 }
407
408
409 type Regs386 struct {
410 AX uint32
411 BX uint32
412 CX uint32
413 DX uint32
414 DI uint32
415 SI uint32
416 BP uint32
417 SP uint32
418 SS uint32
419 FLAGS uint32
420 IP uint32
421 CS uint32
422 DS uint32
423 ES uint32
424 FS uint32
425 GS uint32
426 }
427
428
429 type RegsAMD64 struct {
430 AX uint64
431 BX uint64
432 CX uint64
433 DX uint64
434 DI uint64
435 SI uint64
436 BP uint64
437 SP uint64
438 R8 uint64
439 R9 uint64
440 R10 uint64
441 R11 uint64
442 R12 uint64
443 R13 uint64
444 R14 uint64
445 R15 uint64
446 IP uint64
447 FLAGS uint64
448 CS uint64
449 FS uint64
450 GS uint64
451 }
452
453 type intName struct {
454 i uint32
455 s string
456 }
457
458 func stringName(i uint32, names []intName, goSyntax bool) string {
459 for _, n := range names {
460 if n.i == i {
461 if goSyntax {
462 return "macho." + n.s
463 }
464 return n.s
465 }
466 }
467 return "0x" + strconv.FormatUint(uint64(i), 16)
468 }
469
View as plain text