liyujie
2025-08-28 d9927380ed7c8366f762049be9f3fee225860833
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
 
// Mach-O header data structures
// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
 
package macho
 
import "strconv"
 
// A FileHeader represents a Mach-O file header.
type FileHeader struct {
   Magic  uint32
   Cpu    Cpu
   SubCpu uint32
   Type   Type
   Ncmd   uint32
   Cmdsz  uint32
   Flags  uint32
}
 
const (
   fileHeaderSize32 = 7 * 4
   fileHeaderSize64 = 8 * 4
)
 
const (
   Magic32  uint32 = 0xfeedface
   Magic64  uint32 = 0xfeedfacf
   MagicFat uint32 = 0xcafebabe
)
 
// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
type Type uint32
 
const (
   TypeObj    Type = 1
   TypeExec   Type = 2
   TypeDylib  Type = 6
   TypeBundle Type = 8
)
 
var typeStrings = []intName{
   {uint32(TypeObj), "Obj"},
   {uint32(TypeExec), "Exec"},
   {uint32(TypeDylib), "Dylib"},
   {uint32(TypeBundle), "Bundle"},
}
 
func (t Type) String() string   { return stringName(uint32(t), typeStrings, false) }
func (t Type) GoString() string { return stringName(uint32(t), typeStrings, true) }
 
// A Cpu is a Mach-O cpu type.
type Cpu uint32
 
const cpuArch64 = 0x01000000
 
const (
   Cpu386   Cpu = 7
   CpuAmd64 Cpu = Cpu386 | cpuArch64
   CpuArm   Cpu = 12
   CpuArm64 Cpu = CpuArm | cpuArch64
   CpuPpc   Cpu = 18
   CpuPpc64 Cpu = CpuPpc | cpuArch64
)
 
var cpuStrings = []intName{
   {uint32(Cpu386), "Cpu386"},
   {uint32(CpuAmd64), "CpuAmd64"},
   {uint32(CpuArm), "CpuArm"},
   {uint32(CpuArm64), "CpuArm64"},
   {uint32(CpuPpc), "CpuPpc"},
   {uint32(CpuPpc64), "CpuPpc64"},
}
 
func (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }
func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }
 
// A LoadCmd is a Mach-O load command.
type LoadCmd uint32
 
const (
   LoadCmdSegment    LoadCmd = 0x1
   LoadCmdSymtab     LoadCmd = 0x2
   LoadCmdThread     LoadCmd = 0x4
   LoadCmdUnixThread LoadCmd = 0x5 // thread+stack
   LoadCmdDysymtab   LoadCmd = 0xb
   LoadCmdDylib      LoadCmd = 0xc // load dylib command
   LoadCmdDylinker   LoadCmd = 0xf // id dylinker command (not load dylinker command)
   LoadCmdSegment64  LoadCmd = 0x19
   LoadCmdRpath      LoadCmd = 0x8000001c
)
 
var cmdStrings = []intName{
   {uint32(LoadCmdSegment), "LoadCmdSegment"},
   {uint32(LoadCmdThread), "LoadCmdThread"},
   {uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
   {uint32(LoadCmdDylib), "LoadCmdDylib"},
   {uint32(LoadCmdSegment64), "LoadCmdSegment64"},
   {uint32(LoadCmdRpath), "LoadCmdRpath"},
}
 
func (i LoadCmd) String() string   { return stringName(uint32(i), cmdStrings, false) }
func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }
 
type (
   // A Segment32 is a 32-bit Mach-O segment load command.
   Segment32 struct {
       Cmd     LoadCmd
       Len     uint32
       Name    [16]byte
       Addr    uint32
       Memsz   uint32
       Offset  uint32
       Filesz  uint32
       Maxprot uint32
       Prot    uint32
       Nsect   uint32
       Flag    uint32
   }
 
   // A Segment64 is a 64-bit Mach-O segment load command.
   Segment64 struct {
       Cmd     LoadCmd
       Len     uint32
       Name    [16]byte
       Addr    uint64
       Memsz   uint64
       Offset  uint64
       Filesz  uint64
       Maxprot uint32
       Prot    uint32
       Nsect   uint32
       Flag    uint32
   }
 
   // A SymtabCmd is a Mach-O symbol table command.
   SymtabCmd struct {
       Cmd     LoadCmd
       Len     uint32
       Symoff  uint32
       Nsyms   uint32
       Stroff  uint32
       Strsize uint32
   }
 
   // A DysymtabCmd is a Mach-O dynamic symbol table command.
   DysymtabCmd struct {
       Cmd            LoadCmd
       Len            uint32
       Ilocalsym      uint32
       Nlocalsym      uint32
       Iextdefsym     uint32
       Nextdefsym     uint32
       Iundefsym      uint32
       Nundefsym      uint32
       Tocoffset      uint32
       Ntoc           uint32
       Modtaboff      uint32
       Nmodtab        uint32
       Extrefsymoff   uint32
       Nextrefsyms    uint32
       Indirectsymoff uint32
       Nindirectsyms  uint32
       Extreloff      uint32
       Nextrel        uint32
       Locreloff      uint32
       Nlocrel        uint32
   }
 
   // A DylibCmd is a Mach-O load dynamic library command.
   DylibCmd struct {
       Cmd            LoadCmd
       Len            uint32
       Name           uint32
       Time           uint32
       CurrentVersion uint32
       CompatVersion  uint32
   }
 
   // A RpathCmd is a Mach-O rpath command.
   RpathCmd struct {
       Cmd  LoadCmd
       Len  uint32
       Path uint32
   }
 
   // A Thread is a Mach-O thread state command.
   Thread struct {
       Cmd  LoadCmd
       Len  uint32
       Type uint32
       Data []uint32
   }
)
 
const (
   FlagNoUndefs              uint32 = 0x1
   FlagIncrLink              uint32 = 0x2
   FlagDyldLink              uint32 = 0x4
   FlagBindAtLoad            uint32 = 0x8
   FlagPrebound              uint32 = 0x10
   FlagSplitSegs             uint32 = 0x20
   FlagLazyInit              uint32 = 0x40
   FlagTwoLevel              uint32 = 0x80
   FlagForceFlat             uint32 = 0x100
   FlagNoMultiDefs           uint32 = 0x200
   FlagNoFixPrebinding       uint32 = 0x400
   FlagPrebindable           uint32 = 0x800
   FlagAllModsBound          uint32 = 0x1000
   FlagSubsectionsViaSymbols uint32 = 0x2000
   FlagCanonical             uint32 = 0x4000
   FlagWeakDefines           uint32 = 0x8000
   FlagBindsToWeak           uint32 = 0x10000
   FlagAllowStackExecution   uint32 = 0x20000
   FlagRootSafe              uint32 = 0x40000
   FlagSetuidSafe            uint32 = 0x80000
   FlagNoReexportedDylibs    uint32 = 0x100000
   FlagPIE                   uint32 = 0x200000
   FlagDeadStrippableDylib   uint32 = 0x400000
   FlagHasTLVDescriptors     uint32 = 0x800000
   FlagNoHeapExecution       uint32 = 0x1000000
   FlagAppExtensionSafe      uint32 = 0x2000000
)
 
// A Section32 is a 32-bit Mach-O section header.
type Section32 struct {
   Name     [16]byte
   Seg      [16]byte
   Addr     uint32
   Size     uint32
   Offset   uint32
   Align    uint32
   Reloff   uint32
   Nreloc   uint32
   Flags    uint32
   Reserve1 uint32
   Reserve2 uint32
}
 
// A Section64 is a 64-bit Mach-O section header.
type Section64 struct {
   Name     [16]byte
   Seg      [16]byte
   Addr     uint64
   Size     uint64
   Offset   uint32
   Align    uint32
   Reloff   uint32
   Nreloc   uint32
   Flags    uint32
   Reserve1 uint32
   Reserve2 uint32
   Reserve3 uint32
}
 
// An Nlist32 is a Mach-O 32-bit symbol table entry.
type Nlist32 struct {
   Name  uint32
   Type  uint8
   Sect  uint8
   Desc  uint16
   Value uint32
}
 
// An Nlist64 is a Mach-O 64-bit symbol table entry.
type Nlist64 struct {
   Name  uint32
   Type  uint8
   Sect  uint8
   Desc  uint16
   Value uint64
}
 
// Regs386 is the Mach-O 386 register structure.
type Regs386 struct {
   AX    uint32
   BX    uint32
   CX    uint32
   DX    uint32
   DI    uint32
   SI    uint32
   BP    uint32
   SP    uint32
   SS    uint32
   FLAGS uint32
   IP    uint32
   CS    uint32
   DS    uint32
   ES    uint32
   FS    uint32
   GS    uint32
}
 
// RegsAMD64 is the Mach-O AMD64 register structure.
type RegsAMD64 struct {
   AX    uint64
   BX    uint64
   CX    uint64
   DX    uint64
   DI    uint64
   SI    uint64
   BP    uint64
   SP    uint64
   R8    uint64
   R9    uint64
   R10   uint64
   R11   uint64
   R12   uint64
   R13   uint64
   R14   uint64
   R15   uint64
   IP    uint64
   FLAGS uint64
   CS    uint64
   FS    uint64
   GS    uint64
}
 
type intName struct {
   i uint32
   s string
}
 
func stringName(i uint32, names []intName, goSyntax bool) string {
   for _, n := range names {
       if n.i == i {
           if goSyntax {
               return "macho." + n.s
           }
           return n.s
       }
   }
   return strconv.FormatUint(uint64(i), 10)
}