1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Mach-O header data structures
6// Originally at:
7// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apply)
8// Archived copy at:
9// https://web.archive.org/web/20090819232456/http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/index.html
10// For cloned PDF see:
11// https://github.com/aidansteele/osx-abi-macho-file-format-reference
12
13package macho
14
15import "strconv"
16
17// A FileHeader represents a Mach-O file header.
18type FileHeader struct {
19	Magic  uint32
20	Cpu    Cpu
21	SubCpu uint32
22	Type   Type
23	Ncmd   uint32
24	Cmdsz  uint32
25	Flags  uint32
26}
27
28const (
29	fileHeaderSize32 = 7 * 4
30	fileHeaderSize64 = 8 * 4
31)
32
33const (
34	Magic32  uint32 = 0xfeedface
35	Magic64  uint32 = 0xfeedfacf
36	MagicFat uint32 = 0xcafebabe
37)
38
39// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
40type Type uint32
41
42const (
43	TypeObj    Type = 1
44	TypeExec   Type = 2
45	TypeDylib  Type = 6
46	TypeBundle Type = 8
47)
48
49var typeStrings = []intName{
50	{uint32(TypeObj), "Obj"},
51	{uint32(TypeExec), "Exec"},
52	{uint32(TypeDylib), "Dylib"},
53	{uint32(TypeBundle), "Bundle"},
54}
55
56func (t Type) String() string   { return stringName(uint32(t), typeStrings, false) }
57func (t Type) GoString() string { return stringName(uint32(t), typeStrings, true) }
58
59// A Cpu is a Mach-O cpu type.
60type Cpu uint32
61
62const cpuArch64 = 0x01000000
63
64const (
65	Cpu386   Cpu = 7
66	CpuAmd64 Cpu = Cpu386 | cpuArch64
67	CpuArm   Cpu = 12
68	CpuArm64 Cpu = CpuArm | cpuArch64
69	CpuPpc   Cpu = 18
70	CpuPpc64 Cpu = CpuPpc | cpuArch64
71)
72
73var cpuStrings = []intName{
74	{uint32(Cpu386), "Cpu386"},
75	{uint32(CpuAmd64), "CpuAmd64"},
76	{uint32(CpuArm), "CpuArm"},
77	{uint32(CpuArm64), "CpuArm64"},
78	{uint32(CpuPpc), "CpuPpc"},
79	{uint32(CpuPpc64), "CpuPpc64"},
80}
81
82func (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }
83func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }
84
85// A LoadCmd is a Mach-O load command.
86type LoadCmd uint32
87
88const (
89	LoadCmdSegment    LoadCmd = 0x1
90	LoadCmdSymtab     LoadCmd = 0x2
91	LoadCmdThread     LoadCmd = 0x4
92	LoadCmdUnixThread LoadCmd = 0x5 // thread+stack
93	LoadCmdDysymtab   LoadCmd = 0xb
94	LoadCmdDylib      LoadCmd = 0xc // load dylib command
95	LoadCmdDylinker   LoadCmd = 0xf // id dylinker command (not load dylinker command)
96	LoadCmdSegment64  LoadCmd = 0x19
97	LoadCmdRpath      LoadCmd = 0x8000001c
98)
99
100var cmdStrings = []intName{
101	{uint32(LoadCmdSegment), "LoadCmdSegment"},
102	{uint32(LoadCmdThread), "LoadCmdThread"},
103	{uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
104	{uint32(LoadCmdDylib), "LoadCmdDylib"},
105	{uint32(LoadCmdSegment64), "LoadCmdSegment64"},
106	{uint32(LoadCmdRpath), "LoadCmdRpath"},
107}
108
109func (i LoadCmd) String() string   { return stringName(uint32(i), cmdStrings, false) }
110func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }
111
112type (
113	// A Segment32 is a 32-bit Mach-O segment load command.
114	Segment32 struct {
115		Cmd     LoadCmd
116		Len     uint32
117		Name    [16]byte
118		Addr    uint32
119		Memsz   uint32
120		Offset  uint32
121		Filesz  uint32
122		Maxprot uint32
123		Prot    uint32
124		Nsect   uint32
125		Flag    uint32
126	}
127
128	// A Segment64 is a 64-bit Mach-O segment load command.
129	Segment64 struct {
130		Cmd     LoadCmd
131		Len     uint32
132		Name    [16]byte
133		Addr    uint64
134		Memsz   uint64
135		Offset  uint64
136		Filesz  uint64
137		Maxprot uint32
138		Prot    uint32
139		Nsect   uint32
140		Flag    uint32
141	}
142
143	// A SymtabCmd is a Mach-O symbol table command.
144	SymtabCmd struct {
145		Cmd     LoadCmd
146		Len     uint32
147		Symoff  uint32
148		Nsyms   uint32
149		Stroff  uint32
150		Strsize uint32
151	}
152
153	// A DysymtabCmd is a Mach-O dynamic symbol table command.
154	DysymtabCmd struct {
155		Cmd            LoadCmd
156		Len            uint32
157		Ilocalsym      uint32
158		Nlocalsym      uint32
159		Iextdefsym     uint32
160		Nextdefsym     uint32
161		Iundefsym      uint32
162		Nundefsym      uint32
163		Tocoffset      uint32
164		Ntoc           uint32
165		Modtaboff      uint32
166		Nmodtab        uint32
167		Extrefsymoff   uint32
168		Nextrefsyms    uint32
169		Indirectsymoff uint32
170		Nindirectsyms  uint32
171		Extreloff      uint32
172		Nextrel        uint32
173		Locreloff      uint32
174		Nlocrel        uint32
175	}
176
177	// A DylibCmd is a Mach-O load dynamic library command.
178	DylibCmd struct {
179		Cmd            LoadCmd
180		Len            uint32
181		Name           uint32
182		Time           uint32
183		CurrentVersion uint32
184		CompatVersion  uint32
185	}
186
187	// A RpathCmd is a Mach-O rpath command.
188	RpathCmd struct {
189		Cmd  LoadCmd
190		Len  uint32
191		Path uint32
192	}
193
194	// A Thread is a Mach-O thread state command.
195	Thread struct {
196		Cmd  LoadCmd
197		Len  uint32
198		Type uint32
199		Data []uint32
200	}
201)
202
203const (
204	FlagNoUndefs              uint32 = 0x1
205	FlagIncrLink              uint32 = 0x2
206	FlagDyldLink              uint32 = 0x4
207	FlagBindAtLoad            uint32 = 0x8
208	FlagPrebound              uint32 = 0x10
209	FlagSplitSegs             uint32 = 0x20
210	FlagLazyInit              uint32 = 0x40
211	FlagTwoLevel              uint32 = 0x80
212	FlagForceFlat             uint32 = 0x100
213	FlagNoMultiDefs           uint32 = 0x200
214	FlagNoFixPrebinding       uint32 = 0x400
215	FlagPrebindable           uint32 = 0x800
216	FlagAllModsBound          uint32 = 0x1000
217	FlagSubsectionsViaSymbols uint32 = 0x2000
218	FlagCanonical             uint32 = 0x4000
219	FlagWeakDefines           uint32 = 0x8000
220	FlagBindsToWeak           uint32 = 0x10000
221	FlagAllowStackExecution   uint32 = 0x20000
222	FlagRootSafe              uint32 = 0x40000
223	FlagSetuidSafe            uint32 = 0x80000
224	FlagNoReexportedDylibs    uint32 = 0x100000
225	FlagPIE                   uint32 = 0x200000
226	FlagDeadStrippableDylib   uint32 = 0x400000
227	FlagHasTLVDescriptors     uint32 = 0x800000
228	FlagNoHeapExecution       uint32 = 0x1000000
229	FlagAppExtensionSafe      uint32 = 0x2000000
230)
231
232// A Section32 is a 32-bit Mach-O section header.
233type Section32 struct {
234	Name     [16]byte
235	Seg      [16]byte
236	Addr     uint32
237	Size     uint32
238	Offset   uint32
239	Align    uint32
240	Reloff   uint32
241	Nreloc   uint32
242	Flags    uint32
243	Reserve1 uint32
244	Reserve2 uint32
245}
246
247// A Section64 is a 64-bit Mach-O section header.
248type Section64 struct {
249	Name     [16]byte
250	Seg      [16]byte
251	Addr     uint64
252	Size     uint64
253	Offset   uint32
254	Align    uint32
255	Reloff   uint32
256	Nreloc   uint32
257	Flags    uint32
258	Reserve1 uint32
259	Reserve2 uint32
260	Reserve3 uint32
261}
262
263// An Nlist32 is a Mach-O 32-bit symbol table entry.
264type Nlist32 struct {
265	Name  uint32
266	Type  uint8
267	Sect  uint8
268	Desc  uint16
269	Value uint32
270}
271
272// An Nlist64 is a Mach-O 64-bit symbol table entry.
273type Nlist64 struct {
274	Name  uint32
275	Type  uint8
276	Sect  uint8
277	Desc  uint16
278	Value uint64
279}
280
281// Regs386 is the Mach-O 386 register structure.
282type Regs386 struct {
283	AX    uint32
284	BX    uint32
285	CX    uint32
286	DX    uint32
287	DI    uint32
288	SI    uint32
289	BP    uint32
290	SP    uint32
291	SS    uint32
292	FLAGS uint32
293	IP    uint32
294	CS    uint32
295	DS    uint32
296	ES    uint32
297	FS    uint32
298	GS    uint32
299}
300
301// RegsAMD64 is the Mach-O AMD64 register structure.
302type RegsAMD64 struct {
303	AX    uint64
304	BX    uint64
305	CX    uint64
306	DX    uint64
307	DI    uint64
308	SI    uint64
309	BP    uint64
310	SP    uint64
311	R8    uint64
312	R9    uint64
313	R10   uint64
314	R11   uint64
315	R12   uint64
316	R13   uint64
317	R14   uint64
318	R15   uint64
319	IP    uint64
320	FLAGS uint64
321	CS    uint64
322	FS    uint64
323	GS    uint64
324}
325
326type intName struct {
327	i uint32
328	s string
329}
330
331func stringName(i uint32, names []intName, goSyntax bool) string {
332	for _, n := range names {
333		if n.i == i {
334			if goSyntax {
335				return "macho." + n.s
336			}
337			return n.s
338		}
339	}
340	return strconv.FormatUint(uint64(i), 10)
341}
342